Remove all legacy ATA code parts, not used since options ATA_CAM enabled in

most kernels before FreeBSD 9.0.  Remove such modules and respective kernel
options: atadisk, ataraid, atapicd, atapifd, atapist, atapicam.  Remove the
atacontrol utility and some man pages.  Remove useless now options ATA_CAM.

No objections:	current@, stable@
MFC after:	never
This commit is contained in:
Alexander Motin 2013-04-04 07:12:24 +00:00
parent 3b0b7ffbb9
commit 45f6d66569
77 changed files with 5 additions and 15283 deletions

View File

@ -87,7 +87,7 @@ CRUNCH_SUPPRESS_LINK_-tcsh= 1
# headers in addition to the standard 'paths.h' header.
#
CRUNCH_SRCDIRS+= sbin
CRUNCH_PROGS_sbin= atacontrol badsect \
CRUNCH_PROGS_sbin= badsect \
camcontrol ccdconfig clri devfs dmesg dump \
dumpfs dumpon fsck fsck_ffs fsck_msdosfs fsdb \
fsirand gbde geom ifconfig init \

View File

@ -6,7 +6,6 @@
# XXX MISSING: icheck ncheck
SUBDIR=adjkerntz \
atacontrol \
badsect \
camcontrol \
ccdconfig \

View File

@ -1,6 +0,0 @@
#$FreeBSD$
PROG= atacontrol
MAN= atacontrol.8
.include <bsd.prog.mk>

View File

@ -1,405 +0,0 @@
.\"
.\" Copyright (c) 2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
.\" 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$
.\"
.Dd October 9, 2011
.Dt ATACONTROL 8
.Os
.Sh NAME
.Nm atacontrol
.Nd ATA device driver control program
.Pp
This utility was
.Em deprecated
in
.Fx 9.0 .
See
.Sx NOTES .
.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 addspare
.Ar raid disk
.Nm
.Ic rebuild
.Ar raid
.Nm
.Ic status
.Ar raid
.Nm
.Ic mode
.Ar device
.Op Ar mode
.Nm
.Ic info
.Ar channel
.Nm
.Ic cap
.Ar device
.Nm
.Ic spindown
.Ar device
.Op Ar seconds
.Nm
.Ic list
.Sh DESCRIPTION
The
.Nm
utility is a control program that provides the user access and control to the
.Fx
.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 ATA channel device (e.g., ata0) on which to operate.
The following commands are supported:
.Bl -tag -width ".Ic addspare"
.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 ,
.Cm SPAN
or
.Cm 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 addspare
Add a spare disk to an existing RAID.
.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
.Ar mode
argument, the current transfer mode of the
device are printed.
If the
.Ar mode
argument is given, the ATA driver
is asked to change the transfer mode to the one 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.
.Pp
Currently supported modes are:
.Cm BIOSPIO , PIO0 , PIO1 , PIO2 , PIO3 , PIO4 , WDMA2 , UDMA2
(alias
.Cm UDMA33 ) ,
.Cm UDMA4
(alias
.Cm UDMA66 ) ,
.Cm UDMA5
(alias
.Cm UDMA100 ) ,
.Cm UDMA6
(alias
.Cm UDMA133 ) ,
.Cm SATA150 , SATA300 , USB , USB1 , USB2
and
.Cm BIOSDMA .
.It Ic cap
Show detailed info about the device on
.Ar device .
.It Ic spindown
Set or report timeout after which the
.Ar device
will be spun down.
To arm the timeout the device needs at least one more request after
setting the timeout.
To disable spindown, set the timeout to zero.
No further actions are needed in this case.
.It Ic info
Show info about the attached devices on the
.Ar channel .
The device name and manufacture/version strings are shown.
.It Ic list
Show info about all attached devices on all active controllers.
.El
.Sh EXAMPLES
To get information on devices attached to a channel,
use the command line:
.Pp
.Dl "atacontrol info ata0"
.Pp
To see the devices' current access modes, use the command line:
.Pp
.Dl "atacontrol mode ad0"
.Pp
which results in the modes of the devices being displayed as a string
like this:
.Pp
.Dl "current mode = UDMA100"
.Pp
You can set the mode with
.Nm
and a string like the above,
for example:
.Pp
.Dl "atacontrol mode ad0 PIO4"
.Pp
The new modes are set as soon as the
.Nm
command returns.
.Pp
The atacontrol command can also be used to create purely software
RAID arrays in systems that do NOT have a "real" hardware RAID card
such as a Highpoint or Promise card.
A common scenario is a 1U server such as the HP DL320 G4 or G5.
These servers contain a SATA controller that has 2 channels that can
contain 2 disks per channel, but the servers are wired to only place
a single SATA drive on each channel.
These servers do have a "pseudo" RAID BIOS but it uses a proprietary
format that is not compatible with the ata driver, and thus their
RAID bios must be switched off.
Another common scenario would be a Promise UDMA100 controller card
that did not contain the Fasttrack RAID BIOS, but did contain 2
UDMA channels.
1 disk would be attached to one channel and the other disk would be
attached to the other channel.
It is NOT recommended to create such arrays on a primary/secondary
pair on a SINGLE channel since the throughput of the mirror would be
severely compromised, the ability to rebuild the array in the event
of a disk failure would be greatly complicated, and if a disk
controller electronics failed it could wedge the channel and take
both disks in the mirror offline.
(which would defeat the purpose of having a mirror in the first place)
.Pp
A quick and dirty way to create such a mirrored array on a new
system is to boot off the FreeBSD install CD, do a minimal scratch
install, abort out of the post install questions, and at the command
line issue the command:
.Pp
.Dl "atacontrol create RAID1 ad4 ad6"
.Pp
then immediately issue a reboot and boot from the installation CD
again, and during the installation, you will now see "ar0" listed
as a disk to install on, and install on that instead of ad4, ad6, etc.
.Pp
To get information about the status of a RAID array in the system
use the command line:
.Pp
.Dl "atacontrol status ar0"
.Pp
A typical output showing good health on a RAID array might be as
follows:
.Pp
.Dl "ar0: ATA RAID1 subdisks: ad4 ad6 status: READY"
.Pp
If a disk drive in a RAID1 array dies the system will mark the disk
in a DOWN state and change the array status to DEGRADED.
This can ALSO happen in rare instances due to a power fluctuation or
other event causing the system to not shutdown properly.
In that case the output will look like the following:
.Pp
.Dl "ar0: ATA RAID1 subdisks: ad4 DOWN status: DEGRADED"
.Pp
For a mirrored RAID1 system the server WILL ALLOW you to remove a
dead SATA disk drive (if the drive is in a hot-swap tray) without
freezing up the system, so you can remove the disk and while you are
obtaining a replacement the server can run from the active disk.
The only caveat is that if the active disk is ad6, the system most
likely will NOT be able to be rebooted since most systems only
support booting from the first disk drive.
.Pp
To deactivate the DOWN disk ad6 to allow for it to be ejected, use
the following:
.Pp
.Dl "atacontrol detach ata3"
.Pp
then eject or remove the disk.
Note that this only works if the 2 disks in the mirror are on separate
channels (which is the standard setup for 1-U servers like the HP DL320).
When the new disk drive is obtained, make sure it is blank, then shut
the system down.
At this point, if the system has a RAID array card like a Highpoint or
Promise controller, you may then boot it into the BIOS of the card and use
the manufacturers RAID array rebuild utilities to rebuild the array.
.Pp
If the system has a pure software array and is not using a "real" ATA
RAID controller, then shut the system down, make sure that the disk
that was still working is moved to the bootable position (channel 0
or whatever the BIOS allows the system to boot from) and the blank disk
is placed in the secondary position, then boot the system into
single-user mode and issue the command:
.Pp
.Dl "atacontrol addspare ar0 ad6"
.Dl "atacontrol rebuild ar0"
.Pp
If the disk drive did NOT fail and the RAID array became unmirrored due
to a software glitch or improper shutdown, then a slightly different
process must be followed.
Begin by issuing the detach command (this shows the detach for disk ad6,
the primary master on channel 3):
.Pp
.Dl "atacontrol detach ata3"
.Pp
then reboot the system into single-user mode.
(don't just init the system, reboot it so that both disks get probed)
You will probably see TWO mirrored RAID arrays appear during the boot
messages, ar0 and ar1.
Issue the command:
.Pp
.Dl "atacontrol delete ar1"
.Dl "atacontrol addspare ar0 ad6"
.Pp
Now a status command will show the array rebuilding.
.Pp
To spin down a disk after 30 minutes run
.Pp
.Dl "atacontrol spindown ad6 1800"
.Dl "dd if=/dev/ad6 of=/dev/null count=1"
.Pp
While any IO on the disk will arm the timer, using
.Xr dd 1
on the raw device will work in all cases, as when the disk is not
opened at all.
You can check the current setting with
.Pp
.Dl "atacontrol spindown ad6"
.Pp
You should not set a spindown timeout on a disk with
.Pa /
or syslog logging on it as the disk will be worn out spinning down and
up all the time.
.Sh SEE ALSO
.Xr ata 4 ,
.Xr cam 4 ,
.Xr camcontrol 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Fx 4.6 .
.Pp
.Nm
was deprecated in
.Fx 9.0 .
.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 .
.Sh NOTES
The
.Nm
utility was deprecated in
.Fx 9.0 .
When
.Bd -ragged -offset indent
.Cd "options ATA_CAM"
.Ed
.Pp
is compiled into the kernel, then
.Xr camcontrol 8
must be used instead.

View File

@ -1,644 +0,0 @@
/*-
* Copyright (c) 2000 - 2006 Søren Schmidt <sos@FreeBSD.org>
* 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.
*
* 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$
*/
#include <sys/types.h>
#include <sys/ata.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
static const char *
mode2str(int mode)
{
switch (mode & 0xff) {
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_WDMA0: return "WDMA0";
case ATA_WDMA1: return "WDMA1";
case ATA_WDMA2: return "WDMA2";
case ATA_UDMA0: return "UDMA0";
case ATA_UDMA1: return "UDMA1";
case ATA_UDMA2: return "UDMA33";
case ATA_UDMA3: return "UDMA44";
case ATA_UDMA4: return "UDMA66";
case ATA_UDMA5: return "UDMA100";
case ATA_UDMA6: return "UDMA133";
case ATA_DMA: return "BIOSDMA";
default: return "???";
}
}
static const char *
satarev2str(int mode)
{
switch ((mode & 0xff00) >> 8) {
case 0: return "";
case 1: return "SATA 1.5Gb/s";
case 2: return "SATA 3Gb/s";
case 3: return "SATA 6Gb/s";
case 0xff: return "SATA";
default: return "???";
}
}
static 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, "WDMA0")) return ATA_WDMA0;
if (!strcasecmp(str, "WDMA1")) return ATA_WDMA1;
if (!strcasecmp(str, "WDMA2")) return ATA_WDMA2;
if (!strcasecmp(str, "UDMA0")) return ATA_UDMA0;
if (!strcasecmp(str, "UDMA16")) return ATA_UDMA0;
if (!strcasecmp(str, "UDMA1")) return ATA_UDMA1;
if (!strcasecmp(str, "UDMA25")) return ATA_UDMA1;
if (!strcasecmp(str, "UDMA2")) return ATA_UDMA2;
if (!strcasecmp(str, "UDMA33")) return ATA_UDMA2;
if (!strcasecmp(str, "UDMA3")) return ATA_UDMA3;
if (!strcasecmp(str, "UDMA44")) return ATA_UDMA3;
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;
}
static void
usage(void)
{
fprintf(stderr,
"usage: atacontrol <command> args:\n"
" atacontrol list\n"
" atacontrol info channel\n"
" atacontrol attach channel\n"
" atacontrol detach channel\n"
" atacontrol reinit channel\n"
" atacontrol create type [interleave] disk0 ... diskN\n"
" atacontrol delete array\n"
" atacontrol addspare array disk\n"
" atacontrol rebuild array\n"
" atacontrol status array\n"
" atacontrol mode device [mode]\n"
" atacontrol cap device\n"
" atacontrol spindown device [seconds]\n"
);
exit(EX_USAGE);
}
static 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;
}
static void
param_print(struct ata_params *parm)
{
printf("<%.40s/%.8s> ", parm->model, parm->revision);
if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
if (parm->satacapabilities & ATA_SATA_GEN2)
printf("SATA revision 2.x\n");
else if (parm->satacapabilities & ATA_SATA_GEN1)
printf("SATA revision 1.x\n");
else
printf("Unknown SATA revision\n");
}
else
printf("ATA/ATAPI revision %d\n", version(parm->version_major));
}
static void
cap_print(struct ata_params *parm)
{
u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
((u_int32_t)parm->lba_size_2 << 16);
u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
((u_int64_t)parm->lba_size48_2 << 16) |
((u_int64_t)parm->lba_size48_3 << 32) |
((u_int64_t)parm->lba_size48_4 << 48);
printf("\n");
printf("Protocol ");
if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
if (parm->satacapabilities & ATA_SATA_GEN2)
printf("SATA revision 2.x\n");
else if (parm->satacapabilities & ATA_SATA_GEN1)
printf("SATA revision 1.x\n");
else
printf("Unknown SATA revision\n");
}
else
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);
if (parm->config == ATA_PROTO_CFA ||
(parm->support.command2 & ATA_SUPPORT_CFA))
printf("CFA supported\n");
printf("lba%ssupported ",
parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
if (lbasize)
printf("%d sectors\n", lbasize);
else
printf("\n");
printf("lba48%ssupported ",
parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
if (lbasize48)
printf("%ju sectors\n", (uintmax_t)lbasize48);
else
printf("\n");
printf("dma%ssupported\n",
parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
printf("overlap%ssupported\n",
parm->capabilities1 & ATA_SUPPORT_OVERLAP ? " " : " not ");
printf("\nFeature "
"Support Enable Value Vendor\n");
printf("write cache %s %s\n",
parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
printf("read ahead %s %s\n",
parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
printf("Native Command Queuing (NCQ) %s %s"
" %d/0x%02X\n",
parm->satacapabilities & ATA_SUPPORT_NCQ ?
"yes" : "no", " -",
(parm->satacapabilities & ATA_SUPPORT_NCQ) ?
ATA_QUEUE_LEN(parm->queue) : 0,
(parm->satacapabilities & ATA_SUPPORT_NCQ) ?
ATA_QUEUE_LEN(parm->queue) : 0);
}
printf("Tagged Command Queuing (TCQ) %s %s %d/0x%02X\n",
parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
ATA_QUEUE_LEN(parm->queue), ATA_QUEUE_LEN(parm->queue));
printf("SMART %s %s\n",
parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
printf("microcode download %s %s\n",
parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
printf("security %s %s\n",
parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
printf("power management %s %s\n",
parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
printf("advanced power management %s %s %d/0x%02X\n",
parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no",
parm->apm_value, parm->apm_value);
printf("automatic acoustic management %s %s "
"%d/0x%02X %d/0x%02X\n",
parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
ATA_ACOUSTIC_CURRENT(parm->acoustic),
ATA_ACOUSTIC_CURRENT(parm->acoustic),
ATA_ACOUSTIC_VENDOR(parm->acoustic),
ATA_ACOUSTIC_VENDOR(parm->acoustic));
}
static void
ata_cap_print(int fd)
{
struct ata_params params;
if (ioctl(fd, IOCATAGPARM, &params) < 0)
err(1, "ioctl(IOCATAGPARM)");
cap_print(&params);
}
static void
info_print(int fd, int channel, int prchan)
{
struct ata_ioc_devices devices;
devices.channel = channel;
if (ioctl(fd, IOCATADEVICES, &devices) < 0) {
if (!prchan)
err(1, "ioctl(IOCATADEVICES)");
return;
}
if (prchan)
printf("ATA channel %d:\n", channel);
printf("%sMaster: ", prchan ? " " : "");
if (*devices.name[0]) {
printf("%4.4s ", devices.name[0]);
param_print(&devices.params[0]);
}
else
printf(" no device present\n");
printf("%sSlave: ", prchan ? " " : "");
if (*devices.name[1]) {
printf("%4.4s ", devices.name[1]);
param_print(&devices.params[1]);
}
else
printf(" no device present\n");
}
static void
ata_spindown(int fd, const char *dev, const char *arg)
{
int tmo;
if (arg != NULL) {
tmo = strtoul(arg, NULL, 0);
if (ioctl(fd, IOCATASSPINDOWN, &tmo) < 0)
err(1, "ioctl(IOCATASSPINDOWN)");
} else {
if (ioctl(fd, IOCATAGSPINDOWN, &tmo) < 0)
err(1, "ioctl(IOCATAGSPINDOWN)");
if (tmo == 0)
printf("%s: idle spin down disabled\n", dev);
else
printf("%s: spin down after %d seconds idle\n",
dev, tmo);
}
}
static int
open_dev(const char *arg, int mode)
{
int disk, fd;
char device[64];
if (!(sscanf(arg, "ad%d", &disk) == 1 ||
sscanf(arg, "acd%d", &disk) == 1 ||
sscanf(arg, "afd%d", &disk) == 1 ||
sscanf(arg, "ast%d", &disk) == 1)) {
fprintf(stderr, "atacontrol: Invalid device %s\n", arg);
exit(EX_USAGE);
}
sprintf(device, "/dev/%s", arg);
if ((fd = open(device, mode)) < 0)
err(1, "device not found");
return (fd);
}
static int
ar_arg(const char *arg)
{
int array;
if (!(sscanf(arg, "ar%d", &array) == 1)) {
fprintf(stderr, "atacontrol: Invalid array %s\n", arg);
exit(EX_USAGE);
}
return (array);
}
static int
ata_arg(const char *arg)
{
int channel;
if (!(sscanf(arg, "ata%d", &channel) == 1)) {
fprintf(stderr, "atacontrol: Invalid channel %s\n", arg);
exit(EX_USAGE);
}
return (channel);
}
int
main(int argc, char **argv)
{
int fd, mode, channel, array;
if (feature_present("ata_cam")) {
errx(1, "\nATA_CAM option is enabled in kernel.\n"
"Please use camcontrol instead.");
}
if (argc < 2)
usage();
if (!strcmp(argv[1], "mode") && (argc == 3 || argc == 4)) {
fd = open_dev(argv[2], O_RDONLY);
if (argc == 4) {
mode = str2mode(argv[3]);
if (mode == -1)
errx(1, "unknown mode");
if (ioctl(fd, IOCATASMODE, &mode) < 0)
warn("ioctl(IOCATASMODE)");
}
if (argc == 3 || argc == 4) {
if (ioctl(fd, IOCATAGMODE, &mode) < 0)
err(1, "ioctl(IOCATAGMODE)");
printf("current mode = %s %s\n",
mode2str(mode), satarev2str(mode));
}
exit(EX_OK);
}
if (!strcmp(argv[1], "cap") && argc == 3) {
fd = open_dev(argv[2], O_RDONLY);
ata_cap_print(fd);
exit(EX_OK);
}
if (!strcmp(argv[1], "spindown") && (argc == 3 || argc == 4)) {
fd = open_dev(argv[2], O_RDONLY);
ata_spindown(fd, argv[2], argv[3]);
exit(EX_OK);
}
if ((fd = open("/dev/ata", O_RDWR)) < 0)
err(1, "control device not found");
if (!strcmp(argv[1], "list") && argc == 2) {
int maxchannel;
if (ioctl(fd, IOCATAGMAXCHANNEL, &maxchannel) < 0)
err(1, "ioctl(IOCATAGMAXCHANNEL)");
for (channel = 0; channel < maxchannel; channel++)
info_print(fd, channel, 1);
exit(EX_OK);
}
if (!strcmp(argv[1], "info") && argc == 3) {
channel = ata_arg(argv[2]);
info_print(fd, channel, 0);
exit(EX_OK);
}
if (!strcmp(argv[1], "detach") && argc == 3) {
channel = ata_arg(argv[2]);
if (ioctl(fd, IOCATADETACH, &channel) < 0)
err(1, "ioctl(IOCATADETACH)");
exit(EX_OK);
}
if (!strcmp(argv[1], "attach") && argc == 3) {
channel = ata_arg(argv[2]);
if (ioctl(fd, IOCATAATTACH, &channel) < 0)
err(1, "ioctl(IOCATAATTACH)");
info_print(fd, channel, 0);
exit(EX_OK);
}
if (!strcmp(argv[1], "reinit") && argc == 3) {
channel = ata_arg(argv[2]);
if (ioctl(fd, IOCATAREINIT, &channel) < 0)
warn("ioctl(IOCATAREINIT)");
info_print(fd, channel, 0);
exit(EX_OK);
}
if (!strcmp(argv[1], "create")) {
int disk, dev, offset;
struct ata_ioc_raid_config config;
bzero(&config, sizeof(config));
if (argc > 2) {
if (!strcasecmp(argv[2], "RAID0") ||
!strcasecmp(argv[2], "stripe"))
config.type = AR_RAID0;
if (!strcasecmp(argv[2], "RAID1") ||
!strcasecmp(argv[2],"mirror"))
config.type = AR_RAID1;
if (!strcasecmp(argv[2], "RAID0+1") ||
!strcasecmp(argv[2],"RAID10"))
config.type = AR_RAID01;
if (!strcasecmp(argv[2], "RAID5"))
config.type = AR_RAID5;
if (!strcasecmp(argv[2], "SPAN"))
config.type = AR_SPAN;
if (!strcasecmp(argv[2], "JBOD"))
config.type = AR_JBOD;
}
if (!config.type) {
fprintf(stderr, "atacontrol: Invalid RAID type %s\n",
argv[2]);
fprintf(stderr, "atacontrol: Valid RAID types: \n");
fprintf(stderr, " stripe | mirror | "
"RAID0 | RAID1 | RAID0+1 | RAID5 | "
"SPAN | JBOD\n");
exit(EX_USAGE);
}
if (config.type == AR_RAID0 ||
config.type == AR_RAID01 ||
config.type == AR_RAID5) {
if (argc < 4 ||
!sscanf(argv[3], "%d", &config.interleave) == 1) {
fprintf(stderr,
"atacontrol: Invalid interleave %s\n",
argv[3]);
exit(EX_USAGE);
}
offset = 4;
}
else
offset = 3;
for (disk = 0; disk < 16 && (offset + disk) < argc; disk++) {
if (!(sscanf(argv[offset + disk], "ad%d", &dev) == 1)) {
fprintf(stderr,
"atacontrol: Invalid disk %s\n",
argv[offset + disk]);
exit(EX_USAGE);
}
config.disks[disk] = dev;
}
if ((config.type == AR_RAID1 || config.type == AR_RAID01) &&
disk < 2) {
fprintf(stderr, "atacontrol: At least 2 disks must be "
"specified\n");
exit(EX_USAGE);
}
config.total_disks = disk;
if (ioctl(fd, IOCATARAIDCREATE, &config) < 0)
err(1, "ioctl(IOCATARAIDCREATE)");
else
printf("ar%d created\n", config.lun);
exit(EX_OK);
}
if (!strcmp(argv[1], "delete") && argc == 3) {
array = ar_arg(argv[2]);
if (ioctl(fd, IOCATARAIDDELETE, &array) < 0)
warn("ioctl(IOCATARAIDDELETE)");
exit(EX_OK);
}
if (!strcmp(argv[1], "addspare") && argc == 4) {
struct ata_ioc_raid_config config;
config.lun = ar_arg(argv[2]);
if (!(sscanf(argv[3], "ad%d", &config.disks[0]) == 1)) {
fprintf(stderr,
"atacontrol: Invalid disk %s\n", argv[3]);
usage();
}
if (ioctl(fd, IOCATARAIDADDSPARE, &config) < 0)
warn("ioctl(IOCATARAIDADDSPARE)");
exit(EX_OK);
}
if (!strcmp(argv[1], "rebuild") && argc == 3) {
array = ar_arg(argv[2]);
if (ioctl(fd, IOCATARAIDREBUILD, &array) < 0)
warn("ioctl(IOCATARAIDREBUILD)");
else {
char device[64];
char *buffer;
ssize_t len;
int arfd;
if (daemon(0, 1) == -1)
err(1, "daemon");
nice(20);
snprintf(device, sizeof(device), "/dev/ar%d",
array);
if ((arfd = open(device, O_RDONLY)) == -1)
err(1, "open %s", device);
if ((buffer = malloc(1024 * 1024)) == NULL)
err(1, "malloc");
while ((len = read(arfd, buffer, 1024 * 1024)) > 0)
;
if (len == -1)
err(1, "read");
else
fprintf(stderr,
"atacontrol: ar%d rebuild completed\n",
array);
free(buffer);
close(arfd);
}
exit(EX_OK);
}
if (!strcmp(argv[1], "status") && argc == 3) {
struct ata_ioc_raid_status status;
int i, lun, state;
status.lun = ar_arg(argv[2]);
if (ioctl(fd, IOCATARAIDSTATUS, &status) < 0)
err(1, "ioctl(IOCATARAIDSTATUS)");
printf("ar%d: ATA ", status.lun);
switch (status.type) {
case AR_RAID0:
printf("RAID0 stripesize=%d", status.interleave);
break;
case AR_RAID1:
printf("RAID1");
break;
case AR_RAID01:
printf("RAID0+1 stripesize=%d", status.interleave);
break;
case AR_RAID5:
printf("RAID5 stripesize=%d", status.interleave);
break;
case AR_JBOD:
printf("JBOD");
break;
case AR_SPAN:
printf("SPAN");
break;
}
printf(" status: ");
switch (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",
status.progress);
break;
default:
printf("BROKEN\n");
}
printf(" subdisks:\n");
for (i = 0; i < status.total_disks; i++) {
printf(" %2d ", i);
lun = status.disks[i].lun;
state = status.disks[i].state;
if (lun < 0)
printf("---- ");
else
printf("ad%-2d ", lun);
if (state & AR_DISK_ONLINE)
printf("ONLINE");
else if (state & AR_DISK_SPARE)
printf("SPARE");
else if (state & AR_DISK_PRESENT)
printf("OFFLINE");
else
printf("MISSING");
printf("\n");
}
exit(EX_OK);
}
usage();
exit(EX_OK);
}

View File

@ -51,8 +51,6 @@ MAN= aac.4 \
${_asmc.4} \
asr.4 \
ata.4 \
atapicam.4 \
ataraid.4 \
ath.4 \
ath_ahb.4 \
ath_hal.4 \

View File

@ -36,7 +36,6 @@ kernel configuration file:
.Bd -ragged -offset indent
.Cd "device scbus"
.Cd "device ata"
.Cd "options ATA_CAM"
.Ed
.Pp
Alternatively, to load the driver as set of modules at boot time,
@ -79,12 +78,6 @@ prerequisite for the other modules.
The next three lines are generic bus-specific drivers.
Of the rest, ataahci is the AHCI driver.
The others are vendor-specific PCI drivers.
The
.Dv ATA_CAM
option should always remain in the kernel configuration, to make
the driver work as a
.Xr CAM 4
subsystem module.
.Pp
The following tunables are settable from the
.Xr loader 8 :

View File

@ -1,134 +0,0 @@
.\" Copyright (c) 2002, 2004
.\" Thomas Quinot <thomas@FreeBSD.org>. 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.
.\" 3. Neither the name of the author nor the names of any co-contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" 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 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$
.\"
.Dd October 22, 2009
.Dt ATAPICAM 4
.Os
.Sh NAME
.Nm atapicam
.Nd CAM XPT (transport) module for ATAPI devices
.Sh SYNOPSIS
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 ata"
.Cd "device atapicam"
.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
atapicam_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
the SCSI subsystem,
.Xr cam 4 .
.Pp
.Xr ata 4
and
.Xr scbus 4
must be configured in the kernel as well.
The SCSI target drivers
.Xr ( cd 4 ,
.Xr da 4 ,
or
.Xr st 4 )
can then be used to access the devices.
The generic passthrough device,
.Xr pass 4 ,
can also be used to send SCSI commands directly
to the devices through the CAM API.
.Pp
A separate CAM bus is created for each ATA bus in the system.
On each of these buses, target ID 0 is assigned to the master
device, and ID 1 is assigned to the slave
(provided they are ATAPI devices).
.Sh IMPLEMENTATION NOTES
Some SCSI commands are intercepted by the driver, and undergo special
processing in order to work around limitations of ATAPI devices.
Such limitations can be consequences of the ATAPI specification.
For example, ATAPI devices do not implement the 6-byte versions
of
.Dv MODE_SELECT , MODE_SENSE , READ ,
or
.Dv WRITE .
They can also be common bugs, such as hanging when queried for
extended
.Dv INQUIRY
information.
.Sh EXAMPLES
.Bd -literal -offset indent
device ata
device atapicam
device scbus
device cd
device pass
.Ed
.Pp
Add the
.Nm
driver to the kernel.
.Pp
.Dl "camcontrol devlist"
.Pp
Print the list of all devices available through CAM.
.Pp
.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 scsi 4 ,
.Xr atacontrol 8 ,
.Xr camcontrol 8
.Sh HISTORY
The ATAPI/CAM driver first appeared in
.Fx 4.8
and
.Fx 5.0 .
.Sh AUTHORS
The ATAPI/CAM driver was written by
.An Thomas Quinot Aq thomas@FreeBSD.org .
.Sh BUGS
.Nm
and ATAPI-specific target drivers
.Xr ( acd 4 ,
.Xr ast 4 ,
and
.Xr afd 4 )
can be configured in the same kernel.
Simultaneous access to the same device through the SCSI generic drivers
and the ATAPI-specific drivers may cause problems and is strongly discouraged.

View File

@ -1,148 +0,0 @@
.\" Copyright (c) 2005 Christian Brueffer
.\" 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$
.\"
.Dd February 17, 2006
.Dt ATARAID 4
.Os
.Sh NAME
.Nm ataraid
.Nd "ATA software RAID support"
.Sh SYNOPSIS
.Cd "device ata"
.Cd "device ataraid"
.Sh DESCRIPTION
The
.Nm
driver provides support for so-called software RAID
(sometimes referred to as fake RAID or pseudo RAID).
.Pp
When a controller that supports software RAID is instructed to
create a RAID array, its BIOS writes data structures in a specific
metadata format to the disks.
These data structures are picked up by the
.Nm
driver, so that
.Fx
can work with the array.
The
.Nm
driver has to understand the specific metadata format of a
controller BIOS in order to support its RAID capabilities.
.Pp
Read-only support for a metadata format means that
.Fx
can use the given RAID array for normal read/write operations.
Creation and rebuild of such arrays has to be done from the
controller BIOS.
.Pp
Read and write support for a metadata format means that
.Fx
can use the given RAID array for normal read/write operations.
Additionally, the
.Xr atacontrol 8
utility can be used to create, rebuild, update and fail such
RAID arrays.
.Pp
The
.Nm
driver can read the following metadata formats:
.Pp
.Bl -bullet -compact
.It
Adaptec HostRAID
.It
Highpoint V2 RocketRAID
.It
Highpoint V3 RocketRAID
.It
Intel MatrixRAID
.It
Integrated Technology Express (ITE)
.It
JMicron
.It
LSI Logic V2 MegaRAID
.It
LSI Logic V3 MegaRAID
.It
NVIDIA MediaShield
.It
Promise FastTrak
.It
Silicon Image Medley
.It
Silicon Integrated Systems (SiS)
.It
VIA Tech V-RAID
.It
FreeBSD PseudoRAID
.El
.Pp
The
.Nm
driver can write the following metadata formats:
.Pp
.Bl -bullet -compact
.It
Highpoint V2 RocketRAID
.It
Intel MatrixRAID
.It
JMicron
.It
Promise FastTrak
.It
Silicon Integrated Systems (SiS)
.It
VIA Tech V-RAID
.It
FreeBSD PseudoRAID
.El
.Pp
It is also possible to use software RAID on controllers
that do not have special software RAID capabilities.
See
.Xr atacontrol 8
for details.
.Sh FILES
.Bl -tag -width ".Pa /dev/ar*" -compact
.It Pa /dev/ar*
ATA RAID device nodes
.El
.Sh SEE ALSO
.Xr ata 4 ,
.Xr atacontrol 8
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written by
.An S\(/oren Schmidt Aq sos@FreeBSD.org .
This manual page was written by
.An Christian Brueffer Aq brueffer@FreeBSD.org .
.Sh CAVEATS
RAID5 is not supported at this time.
Code exists, but it neither uses nor maintains parity information.

View File

@ -102,7 +102,6 @@ device fdc
# ATA controllers
device ahci # AHCI-compatible SATA controllers
device ata # Legacy ATA/SATA controllers
options ATA_CAM # Handle legacy controllers with CAM
options ATA_STATIC_ID # Static device numbering
device mvs # Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA
device siis # SiliconImage SiI3124/SiI3132/SiI3531 SATA

View File

@ -76,7 +76,6 @@ device md
# SATA
#device ata
#device atadisk
#device mvs
# Serial ports

View File

@ -76,7 +76,6 @@ device da
# SATA
device ata
device atadisk
#device mvs
# Serial ports

View File

@ -93,7 +93,6 @@ device avila_gpio # GPIO pins on J8
device ata
device avila_ata # Gateworks CF/IDE support
options ATA_CAM
device npe # Network Processing Engine
device npe_fw

View File

@ -96,7 +96,6 @@ device cambria_gpio # GPIO pins on J11
device ata
device avila_ata # Gateworks CF/IDE support
options ATA_CAM
device npe # Network Processing Engine
device npe_fw

View File

@ -73,7 +73,6 @@ device uart
device pci
device ata
options ATA_CAM
options ATA_STATIC_ID # Static device numbering
device scbus # SCSI bus (required for ATA/SCSI)

View File

@ -83,7 +83,6 @@ options ROOTDEVNAME=\"ufs:/dev/da0s2\"
# ATA controllers
#device ahci # AHCI-compatible SATA controllers
#device ata # Legacy ATA/SATA controllers
#options ATA_CAM # Handle legacy controllers with CAM
#options ATA_STATIC_ID # Static device numbering
# Console and misc

View File

@ -111,7 +111,6 @@ options ALT_BREAK_TO_DEBUGGER
device ata
device atapci # Only for helper functions
device imxata
options ATA_CAM
options ATA_STATIC_ID # Static device numbering
device iomux # IO Multiplexor

View File

@ -73,7 +73,6 @@ device uart
device pci
device ata
options ATA_CAM
options ATA_STATIC_ID # Static device numbering
device scbus # SCSI bus (required for ATA/SCSI)

View File

@ -72,7 +72,6 @@ device uart
device pci
device ata
options ATA_CAM
options ATA_STATIC_ID # Static device numbering
device scbus # SCSI bus (required for ATA/SCSI)

View File

@ -70,7 +70,6 @@ device da
# SATA
device ata
options ATA_CAM
# Flattened Device Tree
options FDT

View File

@ -411,11 +411,7 @@ static void adasuspend(void *arg);
static void adaresume(void *arg);
#ifndef ADA_DEFAULT_LEGACY_ALIASES
#ifdef ATA_CAM
#define ADA_DEFAULT_LEGACY_ALIASES 1
#else
#define ADA_DEFAULT_LEGACY_ALIASES 0
#endif
#endif
#ifndef ADA_DEFAULT_TIMEOUT

View File

@ -1706,21 +1706,14 @@ device mvs
device siis
#
# The 'ATA' driver supports all ATA and ATAPI devices, including PC Card
# devices. You only need one "device ata" for it to find all
# The 'ATA' driver supports all legacy ATA/ATAPI controllers, including
# PC Card devices. You only need one "device ata" for it to find all
# PCI and PC Card ATA/ATAPI devices on modern machines.
# Alternatively, individual bus and chipset drivers may be chosen by using
# the 'atacore' driver then selecting the drivers on a per vendor basis.
# For example to build a system which only supports a VIA chipset,
# omit 'ata' and include the 'atacore', 'atapci' and 'atavia' drivers.
device ata
#device atadisk # ATA disk drives
#device ataraid # ATA RAID 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)
# Modular ATA
#device atacore # Core ATA functionality
@ -1770,15 +1763,9 @@ hint.ata.1.irq="15"
# else the device numbers are dynamically allocated.
# ATA_REQUEST_TIMEOUT: the number of seconds to wait for an ATA request
# before timing out.
# ATA_CAM: Turn ata(4) subsystem controller drivers into cam(4)
# interface modules. This deprecates all ata(4)
# peripheral device drivers (atadisk, ataraid, atapicd,
# atapifd, atapist, atapicam) and all user-level APIs.
# cam(4) drivers and APIs will be connected instead.
options ATA_STATIC_ID
#options ATA_REQUEST_TIMEOUT=10
options ATA_CAM
#
# Standard floppy disk controllers and floppy tapes, supports

View File

@ -705,12 +705,6 @@ dev/ata/chipsets/ata-serverworks.c optional ata pci | ataserverworks
dev/ata/chipsets/ata-siliconimage.c optional ata pci | atasiliconimage | ataati
dev/ata/chipsets/ata-sis.c optional ata pci | atasis
dev/ata/chipsets/ata-via.c optional ata pci | atavia
dev/ata/ata-disk.c optional atadisk
dev/ata/ata-raid.c optional ataraid
dev/ata/atapi-cd.c optional atapicd
dev/ata/atapi-fd.c optional atapifd
dev/ata/atapi-tape.c optional atapist
dev/ata/atapi-cam.c optional atapicam
#
dev/ath/if_ath_pci.c optional ath_pci pci \
compile-with "${NORMAL_C} -I$S/dev/ath"

View File

@ -88,7 +88,7 @@ sparc64/pci/schizo.c optional pci
sparc64/sbus/dma_sbus.c optional sbus
sparc64/sbus/sbus.c optional sbus
sparc64/sbus/lsi64854.c optional sbus
sparc64/sparc64/ata_machdep.c optional ada | atadisk | da
sparc64/sparc64/ata_machdep.c optional ada | da
sparc64/sparc64/autoconf.c standard
sparc64/sparc64/bus_machdep.c standard
sparc64/sparc64/cache.c standard

View File

@ -366,7 +366,6 @@ ISCSI_INITIATOR_DEBUG opt_iscsi_initiator.h
ATA_STATIC_ID opt_ata.h
ATA_NOPCI opt_ata.h
ATA_REQUEST_TIMEOUT opt_ata.h
ATA_CAM opt_ata.h
# Net stuff.
ACCEPT_FILTER_DATA

File diff suppressed because it is too large Load Diff

View File

@ -423,9 +423,7 @@ struct ata_request {
struct ata_composite *composite; /* for composite atomic ops */
void *driver; /* driver specific */
TAILQ_ENTRY(ata_request) chain; /* list management */
#ifdef ATA_CAM
union ccb *ccb;
#endif
};
/* define this for debugging request processing */
@ -532,7 +530,6 @@ struct ata_resource {
int offset;
};
#ifdef ATA_CAM
struct ata_cam_device {
u_int revision;
int mode;
@ -540,7 +537,6 @@ struct ata_cam_device {
u_int atapi;
u_int caps;
};
#endif
/* structure describing an ATA channel */
struct ata_channel {
@ -580,20 +576,13 @@ struct ata_channel {
#define ATA_ACTIVE 0x0001
#define ATA_STALL_QUEUE 0x0002
#ifndef ATA_CAM
struct mtx queue_mtx; /* queue lock */
TAILQ_HEAD(, ata_request) ata_queue; /* head of ATA queue */
struct ata_request *freezepoint; /* composite freezepoint */
#endif
struct ata_request *running; /* currently running request */
struct task conntask; /* PHY events handling task */
#ifdef ATA_CAM
struct cam_sim *sim;
struct cam_path *path;
struct ata_cam_device user[16]; /* User-specified settings */
struct ata_cam_device curr[16]; /* Current settings */
int requestsense; /* CCB waiting for SENSE. */
#endif
struct callout poll_callout; /* Periodic status poll. */
};
@ -632,17 +621,7 @@ void ata_print_cable(device_t dev, u_int8_t *who);
int ata_str2mode(const char *str);
const char *ata_satarev2str(int rev);
int ata_atapi(device_t dev, int target);
#ifndef ATA_CAM
int ata_identify(device_t dev);
void ata_modify_if_48bit(struct ata_request *request);
int ata_pmode(struct ata_params *ap);
int ata_wmode(struct ata_params *ap);
int ata_umode(struct ata_params *ap);
int ata_limit_mode(device_t dev, int mode, int maxmode);
int ata_check_80pin(device_t dev, int mode);
#else
void ata_cam_end_transaction(device_t dev, struct ata_request *request);
#endif
/* ata-queue.c: */
int ata_controlcmd(device_t dev, u_int8_t command, u_int16_t feature, u_int64_t lba, u_int16_t count);
@ -685,11 +664,6 @@ extern uma_zone_t ata_request_zone;
uma_zfree(ata_request_zone, request); \
}
/* macros for alloc/free of struct ata_composite */
extern uma_zone_t ata_composite_zone;
#define ata_alloc_composite() uma_zalloc(ata_composite_zone, M_NOWAIT | M_ZERO)
#define ata_free_composite(composite) uma_zfree(ata_composite_zone, composite)
MALLOC_DECLARE(M_ATA);
/* misc newbus defines */

View File

@ -53,12 +53,6 @@ struct ata_cbus_controller {
struct resource *bankio;
struct resource *irq;
void *ih;
#ifndef ATA_CAM
struct mtx bank_mtx;
int locked_bank;
int restart_bank;
int hardware_bank;
#endif
int channels;
struct {
void (*function)(void *);
@ -68,9 +62,6 @@ struct ata_cbus_controller {
/* local prototypes */
static void ata_cbus_intr(void *);
#ifndef ATA_CAM
static int ata_cbuschannel_banking(device_t dev, int flags);
#endif
static int
ata_cbus_probe(device_t dev)
@ -160,17 +151,9 @@ ata_cbus_attach(device_t dev)
return ENXIO;
}
#ifndef ATA_CAM
ctlr->channels = 2;
mtx_init(&ctlr->bank_mtx, "ATA cbus bank lock", NULL, MTX_DEF);
ctlr->hardware_bank = -1;
ctlr->locked_bank = -1;
ctlr->restart_bank = -1;
#else
/* Work around the lack of channel serialization in ATA_CAM. */
ctlr->channels = 1;
device_printf(dev, "second channel ignored\n");
#endif
for (unit = 0; unit < ctlr->channels; unit++) {
child = device_add_child(dev, "ata", unit);
@ -244,10 +227,7 @@ ata_cbus_intr(void *data)
for (unit = 0; unit < ctlr->channels; unit++) {
if (!(ch = ctlr->interrupt[unit].argument))
continue;
#ifndef ATA_CAM
if (ata_cbuschannel_banking(ch->dev, ATA_LF_WHICH) == unit)
#endif
ctlr->interrupt[unit].function(ch);
ctlr->interrupt[unit].function(ch);
}
}
@ -349,50 +329,6 @@ ata_cbuschannel_resume(device_t dev)
return ata_resume(dev);
}
#ifndef ATA_CAM
static int
ata_cbuschannel_banking(device_t dev, int flags)
{
struct ata_cbus_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
int res;
mtx_lock(&ctlr->bank_mtx);
switch (flags) {
case ATA_LF_LOCK:
if (ctlr->locked_bank == -1)
ctlr->locked_bank = ch->unit;
if (ctlr->locked_bank == ch->unit) {
ctlr->hardware_bank = ch->unit;
ATA_OUTB(ctlr->bankio, 0, ch->unit);
}
else
ctlr->restart_bank = ch->unit;
break;
case ATA_LF_UNLOCK:
if (ctlr->locked_bank == ch->unit) {
ctlr->locked_bank = -1;
if (ctlr->restart_bank != -1) {
if ((ch = ctlr->interrupt[ctlr->restart_bank].argument)) {
ctlr->restart_bank = -1;
mtx_unlock(&ctlr->bank_mtx);
ata_start(ch->dev);
return -1;
}
}
}
break;
case ATA_LF_WHICH:
break;
}
res = ctlr->locked_bank;
mtx_unlock(&ctlr->bank_mtx);
return res;
}
#endif
static device_method_t ata_cbuschannel_methods[] = {
/* device interface */
DEVMETHOD(device_probe, ata_cbuschannel_probe),
@ -400,11 +336,6 @@ static device_method_t ata_cbuschannel_methods[] = {
DEVMETHOD(device_detach, ata_cbuschannel_detach),
DEVMETHOD(device_suspend, ata_cbuschannel_suspend),
DEVMETHOD(device_resume, ata_cbuschannel_resume),
#ifndef ATA_CAM
/* ATA methods */
DEVMETHOD(ata_locking, ata_cbuschannel_banking),
#endif
DEVMETHOD_END
};

View File

@ -1,607 +0,0 @@
/*-
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* 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.
*
* 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ata.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ata.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/disk.h>
#include <sys/cons.h>
#include <sys/sema.h>
#include <sys/taskqueue.h>
#include <vm/uma.h>
#include <machine/md_var.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <geom/geom_disk.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/ata-pci.h>
#include <dev/ata/ata-disk.h>
#include <dev/ata/ata-raid.h>
#include <dev/pci/pcivar.h>
#include <ata_if.h>
/* prototypes */
static void ad_init(device_t dev);
static int ad_get_geometry(device_t dev);
static void ad_set_geometry(device_t dev);
static void ad_done(struct ata_request *request);
static void ad_describe(device_t dev);
static int ad_version(u_int16_t version);
static disk_strategy_t ad_strategy;
static disk_ioctl_t ad_ioctl;
static dumper_t ad_dump;
/*
* Most platforms map firmware geom to actual, but some don't. If
* not overridden, default to nothing.
*/
#ifndef ata_disk_firmware_geom_adjust
#define ata_disk_firmware_geom_adjust(disk)
#endif
/* local vars */
static MALLOC_DEFINE(M_AD, "ad_driver", "ATA disk driver");
static int
ad_probe(device_t dev)
{
struct ata_device *atadev = device_get_softc(dev);
if (!(atadev->param.config & ATA_PROTO_ATAPI) ||
(atadev->param.config == ATA_CFA_MAGIC1) ||
(atadev->param.config == ATA_CFA_MAGIC2) ||
(atadev->param.config == ATA_CFA_MAGIC3))
return 0;
else
return ENXIO;
}
static int
ad_attach(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
struct ad_softc *adp;
device_t parent;
/* check that we have a virgin disk to attach */
if (device_get_ivars(dev))
return EEXIST;
if (!(adp = malloc(sizeof(struct ad_softc), M_AD, M_NOWAIT | M_ZERO))) {
device_printf(dev, "out of memory\n");
return ENOMEM;
}
device_set_ivars(dev, adp);
/* get device geometry into internal structs */
if (ad_get_geometry(dev))
return ENXIO;
/* set the max size if configured */
if (ata_setmax)
ad_set_geometry(dev);
/* init device parameters */
ad_init(dev);
/* announce we are here */
ad_describe(dev);
/* create the disk device */
adp->disk = disk_alloc();
adp->disk->d_strategy = ad_strategy;
adp->disk->d_ioctl = ad_ioctl;
adp->disk->d_dump = ad_dump;
adp->disk->d_name = "ad";
adp->disk->d_drv1 = dev;
adp->disk->d_maxsize = ch->dma.max_iosize ? ch->dma.max_iosize : DFLTPHYS;
if (atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48)
adp->disk->d_maxsize = min(adp->disk->d_maxsize, 65536 * DEV_BSIZE);
else /* 28bit ATA command limit */
adp->disk->d_maxsize = min(adp->disk->d_maxsize, 256 * DEV_BSIZE);
adp->disk->d_sectorsize = DEV_BSIZE;
adp->disk->d_mediasize = DEV_BSIZE * (off_t)adp->total_secs;
adp->disk->d_fwsectors = adp->sectors;
adp->disk->d_fwheads = adp->heads;
adp->disk->d_unit = device_get_unit(dev);
if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
adp->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
if ((atadev->param.support.command2 & ATA_SUPPORT_CFA) ||
atadev->param.config == ATA_PROTO_CFA)
adp->disk->d_flags |= DISKFLAG_CANDELETE;
strlcpy(adp->disk->d_ident, atadev->param.serial,
sizeof(adp->disk->d_ident));
strlcpy(adp->disk->d_descr, atadev->param.model,
sizeof(adp->disk->d_descr));
parent = device_get_parent(ch->dev);
if (parent != NULL && device_get_parent(parent) != NULL &&
(device_get_devclass(parent) ==
devclass_find("atapci") ||
device_get_devclass(device_get_parent(parent)) ==
devclass_find("pci"))) {
adp->disk->d_hba_vendor = pci_get_vendor(parent);
adp->disk->d_hba_device = pci_get_device(parent);
adp->disk->d_hba_subvendor = pci_get_subvendor(parent);
adp->disk->d_hba_subdevice = pci_get_subdevice(parent);
}
ata_disk_firmware_geom_adjust(adp->disk);
disk_create(adp->disk, DISK_VERSION);
device_add_child(dev, "subdisk", device_get_unit(dev));
bus_generic_attach(dev);
callout_init(&atadev->spindown_timer, 1);
return 0;
}
static int
ad_detach(device_t dev)
{
struct ad_softc *adp = device_get_ivars(dev);
struct ata_device *atadev = device_get_softc(dev);
/* check that we have a valid disk to detach */
if (!device_get_ivars(dev))
return ENXIO;
/* destroy the power timeout */
callout_drain(&atadev->spindown_timer);
/* detach & delete all children */
device_delete_children(dev);
/* destroy disk from the system so we don't get any further requests */
disk_destroy(adp->disk);
/* fail requests on the queue and any that's "in flight" for this device */
ata_fail_requests(dev);
/* don't leave anything behind */
device_set_ivars(dev, NULL);
free(adp, M_AD);
return 0;
}
static int
ad_shutdown(device_t dev)
{
struct ata_device *atadev = device_get_softc(dev);
if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
ata_controlcmd(dev, ATA_FLUSHCACHE, 0, 0, 0);
return 0;
}
static int
ad_reinit(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
/* if detach pending, return error */
if (!(ch->devices & (ATA_ATA_MASTER << atadev->unit)))
return 1;
ad_init(dev);
return 0;
}
static void
ad_power_callback(struct ata_request *request)
{
device_printf(request->dev, "drive spun down.\n");
ata_free_request(request);
}
static void
ad_spindown(void *priv)
{
device_t dev = priv;
struct ata_device *atadev = device_get_softc(dev);
struct ata_request *request;
if (!atadev->spindown)
return;
device_printf(dev, "Idle, spin down\n");
atadev->spindown_state = 1;
if (!(request = ata_alloc_request())) {
device_printf(dev, "FAILURE - out of memory in ad_spindown\n");
return;
}
request->dev = dev;
request->flags = ATA_R_CONTROL;
request->timeout = ATA_REQUEST_TIMEOUT;
request->retries = 1;
request->callback = ad_power_callback;
request->u.ata.command = ATA_STANDBY_IMMEDIATE;
ata_queue_request(request);
}
static void
ad_strategy(struct bio *bp)
{
device_t dev = bp->bio_disk->d_drv1;
struct ata_device *atadev = device_get_softc(dev);
struct ata_request *request;
if (atadev->spindown)
callout_reset(&atadev->spindown_timer, hz * atadev->spindown,
ad_spindown, dev);
if (!(request = ata_alloc_request())) {
device_printf(dev, "FAILURE - out of memory in start\n");
biofinish(bp, NULL, ENOMEM);
return;
}
/* setup request */
request->dev = dev;
request->bio = bp;
request->callback = ad_done;
if (atadev->spindown_state) {
device_printf(dev, "request while spun down, starting.\n");
atadev->spindown_state = 0;
request->timeout = MAX(ATA_REQUEST_TIMEOUT, 31);
}
else {
request->timeout = ATA_REQUEST_TIMEOUT;
}
request->retries = 2;
request->data = bp->bio_data;
request->bytecount = bp->bio_bcount;
request->u.ata.lba = bp->bio_pblkno;
request->u.ata.count = request->bytecount / DEV_BSIZE;
request->transfersize = min(bp->bio_bcount, atadev->max_iosize);
switch (bp->bio_cmd) {
case BIO_READ:
request->flags = ATA_R_READ;
if (atadev->mode >= ATA_DMA) {
request->u.ata.command = ATA_READ_DMA;
request->flags |= ATA_R_DMA;
}
else if (request->transfersize > DEV_BSIZE)
request->u.ata.command = ATA_READ_MUL;
else
request->u.ata.command = ATA_READ;
break;
case BIO_WRITE:
request->flags = ATA_R_WRITE;
if (atadev->mode >= ATA_DMA) {
request->u.ata.command = ATA_WRITE_DMA;
request->flags |= ATA_R_DMA;
}
else if (request->transfersize > DEV_BSIZE)
request->u.ata.command = ATA_WRITE_MUL;
else
request->u.ata.command = ATA_WRITE;
break;
case BIO_DELETE:
request->flags = ATA_R_CONTROL;
request->u.ata.command = ATA_CFA_ERASE;
request->transfersize = 0;
request->donecount = bp->bio_bcount;
break;
case BIO_FLUSH:
request->u.ata.lba = 0;
request->u.ata.count = 0;
request->u.ata.feature = 0;
request->bytecount = 0;
request->transfersize = 0;
request->flags = ATA_R_CONTROL;
request->u.ata.command = ATA_FLUSHCACHE;
break;
default:
device_printf(dev, "FAILURE - unknown BIO operation\n");
ata_free_request(request);
biofinish(bp, NULL, EIO);
return;
}
request->flags |= ATA_R_ORDERED;
ata_queue_request(request);
}
static void
ad_done(struct ata_request *request)
{
struct bio *bp = request->bio;
/* finish up transfer */
if ((bp->bio_error = request->result))
bp->bio_flags |= BIO_ERROR;
bp->bio_resid = bp->bio_bcount - request->donecount;
biodone(bp);
ata_free_request(request);
}
static int
ad_ioctl(struct disk *disk, u_long cmd, void *data, int flag, struct thread *td)
{
return ata_device_ioctl(disk->d_drv1, cmd, data);
}
static int
ad_dump(void *arg, void *virtual, vm_offset_t physical,
off_t offset, size_t length)
{
struct disk *dp = arg;
device_t dev = dp->d_drv1;
struct bio bp;
/* XXX: Drop pre-dump request queue. Long request queue processing
* causes stack overflow in ATA working in dumping (interruptless) mode.
* Conter-XXX: To make dump coherent we should avoid doing anything
* else while dumping.
*/
ata_drop_requests(dev);
/* length zero is special and really means flush buffers to media */
if (!length) {
struct ata_device *atadev = device_get_softc(dev);
int error = 0;
if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
error = ata_controlcmd(dev, ATA_FLUSHCACHE, 0, 0, 0);
return error;
}
bzero(&bp, sizeof(struct bio));
bp.bio_disk = dp;
bp.bio_pblkno = offset / DEV_BSIZE;
bp.bio_bcount = length;
bp.bio_data = virtual;
bp.bio_cmd = BIO_WRITE;
ad_strategy(&bp);
return bp.bio_error;
}
static void
ad_init(device_t dev)
{
struct ata_device *atadev = device_get_softc(dev);
ata_setmode(dev);
/* enable readahead caching */
if (atadev->param.support.command1 & ATA_SUPPORT_LOOKAHEAD)
ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_ENAB_RCACHE, 0, 0);
/* enable write caching if supported and configured */
if (atadev->param.support.command1 & ATA_SUPPORT_WRITECACHE) {
if (ata_wc)
ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_ENAB_WCACHE, 0, 0);
else
ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_DIS_WCACHE, 0, 0);
}
/* use multiple sectors/interrupt if device supports it */
if (ad_version(atadev->param.version_major)) {
int secsperint = max(1, min(atadev->param.sectors_intr & 0xff, 16));
if (!ata_controlcmd(dev, ATA_SET_MULTI, 0, 0, secsperint))
atadev->max_iosize = secsperint * DEV_BSIZE;
else
atadev->max_iosize = DEV_BSIZE;
}
else
atadev->max_iosize = DEV_BSIZE;
}
static int
ad_get_geometry(device_t dev)
{
struct ata_device *atadev = device_get_softc(dev);
struct ad_softc *adp = device_get_ivars(dev);
u_int64_t lbasize48;
u_int32_t lbasize;
if ((atadev->param.atavalid & ATA_FLAG_54_58) &&
atadev->param.current_heads && atadev->param.current_sectors) {
adp->heads = atadev->param.current_heads;
adp->sectors = atadev->param.current_sectors;
adp->total_secs = (u_int32_t)atadev->param.current_size_1 |
((u_int32_t)atadev->param.current_size_2 << 16);
}
else {
adp->heads = atadev->param.heads;
adp->sectors = atadev->param.sectors;
adp->total_secs = atadev->param.cylinders * adp->heads * adp->sectors;
}
lbasize = (u_int32_t)atadev->param.lba_size_1 |
((u_int32_t)atadev->param.lba_size_2 << 16);
/* This device exists, but has no size. Filter out this bogus device. */
if (!lbasize && !adp->total_secs)
return ENXIO;
/* does this device need oldstyle CHS addressing */
if (!ad_version(atadev->param.version_major) || !lbasize)
atadev->flags |= ATA_D_USE_CHS;
/* use the 28bit LBA size if valid or bigger than the CHS mapping */
if (atadev->param.cylinders == 16383 || adp->total_secs < lbasize)
adp->total_secs = lbasize;
/* use the 48bit LBA size if valid */
lbasize48 = ((u_int64_t)atadev->param.lba_size48_1) |
((u_int64_t)atadev->param.lba_size48_2 << 16) |
((u_int64_t)atadev->param.lba_size48_3 << 32) |
((u_int64_t)atadev->param.lba_size48_4 << 48);
if ((atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48) &&
lbasize48 > ATA_MAX_28BIT_LBA)
adp->total_secs = lbasize48;
return 0;
}
static void
ad_set_geometry(device_t dev)
{
struct ad_softc *adp = device_get_ivars(dev);
struct ata_request *request;
if (1 | bootverbose)
device_printf(dev, "ORG %ju sectors [%juC/%dH/%dS]\n", adp->total_secs,
adp->total_secs / (adp->heads * adp->sectors),
adp->heads, adp->sectors);
if (!(request = ata_alloc_request()))
return;
/* get the max native size the device supports */
request->dev = dev;
request->u.ata.command = ATA_READ_NATIVE_MAX_ADDRESS;
request->u.ata.lba = 0;
request->u.ata.count = 0;
request->u.ata.feature = 0;
request->flags = ATA_R_CONTROL | ATA_R_QUIET;
request->timeout = ATA_REQUEST_TIMEOUT;
request->retries = 0;
ata_queue_request(request);
if (request->status & ATA_S_ERROR)
goto out;
if (1 | bootverbose)
device_printf(dev, "MAX %ju sectors\n", request->u.ata.lba + 1);
/* if original size equals max size nothing more todo */
if (adp->total_secs >= request->u.ata.lba)
goto out;
/* set the max native size to its max */
request->dev = dev;
request->u.ata.command = ATA_SET_MAX_ADDRESS;
request->u.ata.count = 1;
request->u.ata.feature = 0;
request->flags = ATA_R_CONTROL;
request->timeout = ATA_REQUEST_TIMEOUT;
request->retries = 0;
ata_queue_request(request);
if (request->status & ATA_S_ERROR)
goto out;
/* refresh geometry from drive */
ata_getparam(device_get_softc(dev), 0);
ad_get_geometry(dev);
if (1 | bootverbose)
device_printf(dev, "NEW %ju sectors [%juC/%dH/%dS]\n", adp->total_secs,
adp->total_secs / (adp->heads * adp->sectors),
adp->heads, adp->sectors);
out:
ata_free_request(request);
}
static void
ad_describe(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
struct ad_softc *adp = device_get_ivars(dev);
u_int8_t *marker, vendor[64], product[64];
/* try to separate the ATA model string into vendor and model parts */
if ((marker = strchr(atadev->param.model, ' ')) ||
(marker = strchr(atadev->param.model, '-'))) {
int len = (marker - atadev->param.model);
strncpy(vendor, atadev->param.model, len);
vendor[len++] = 0;
strcat(vendor, " ");
strncpy(product, atadev->param.model + len, 40 - len);
vendor[40 - len] = 0;
}
else {
if (!strncmp(atadev->param.model, "ST", 2))
strcpy(vendor, "Seagate ");
else if (!strncmp(atadev->param.model, "HDS", 3))
strcpy(vendor, "Hitachi ");
else
strcpy(vendor, "");
strncpy(product, atadev->param.model, 40);
}
device_printf(dev, "%juMB <%s%s %.8s> at ata%d-%s %s%s %s\n",
adp->total_secs / (1048576 / DEV_BSIZE),
vendor, product, atadev->param.revision,
device_get_unit(ch->dev), ata_unit2str(atadev),
(adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "",
ata_mode2str(atadev->mode),
ata_satarev2str(ATA_GETREV(device_get_parent(dev), atadev->unit)));
if (bootverbose) {
device_printf(dev, "%ju sectors [%juC/%dH/%dS] "
"%d sectors/interrupt %d depth queue\n", adp->total_secs,
adp->total_secs / (adp->heads * adp->sectors),
adp->heads, adp->sectors, atadev->max_iosize / DEV_BSIZE,
adp->num_tags + 1);
}
}
static int
ad_version(u_int16_t version)
{
int bit;
if (version == 0xffff)
return 0;
for (bit = 15; bit >= 0; bit--)
if (version & (1<<bit))
return bit;
return 0;
}
static device_method_t ad_methods[] = {
/* device interface */
DEVMETHOD(device_probe, ad_probe),
DEVMETHOD(device_attach, ad_attach),
DEVMETHOD(device_detach, ad_detach),
DEVMETHOD(device_shutdown, ad_shutdown),
/* ATA methods */
DEVMETHOD(ata_reinit, ad_reinit),
DEVMETHOD_END
};
static driver_t ad_driver = {
"ad",
ad_methods,
0,
};
devclass_t ad_devclass;
DRIVER_MODULE(ad, ata, ad_driver, ad_devclass, NULL, NULL);
MODULE_VERSION(ad, 1);
MODULE_DEPEND(ad, ata, 1, 1, 1);

View File

@ -1,47 +0,0 @@
/*-
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* 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.
*
* 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$
*/
/* structure describing an ATA disk */
struct ad_softc {
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 disk *disk; /* disklabel/slice stuff */
};
extern devclass_t ad_devclass;

View File

@ -304,13 +304,11 @@ ata_dmaload(struct ata_request *request, void *addr, int *entries)
else
dspa.dmatab = request->dma->sg;
#ifdef ATA_CAM
if (request->flags & ATA_R_DATA_IN_CCB)
error = bus_dmamap_load_ccb(request->dma->data_tag,
request->dma->data_map, request->ccb,
ch->dma.setprd, &dspa, BUS_DMA_NOWAIT);
else
#endif
error = bus_dmamap_load(request->dma->data_tag, request->dma->data_map,
request->data, request->bytecount,
ch->dma.setprd, &dspa, BUS_DMA_NOWAIT);

View File

@ -783,9 +783,6 @@ static void
ata_tf_write(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(request->parent);
#ifndef ATA_CAM
struct ata_device *atadev = device_get_softc(request->dev);
#endif
if (request->flags & ATA_R_48BIT) {
ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature >> 8);
@ -803,39 +800,12 @@ ata_tf_write(struct ata_request *request)
else {
ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count);
#ifndef ATA_CAM
if (atadev->flags & ATA_D_USE_CHS) {
int heads, sectors;
if (atadev->param.atavalid & ATA_FLAG_54_58) {
heads = atadev->param.current_heads;
sectors = atadev->param.current_sectors;
}
else {
heads = atadev->param.heads;
sectors = atadev->param.sectors;
}
ATA_IDX_OUTB(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1);
ATA_IDX_OUTB(ch, ATA_CYL_LSB,
(request->u.ata.lba / (sectors * heads)));
ATA_IDX_OUTB(ch, ATA_CYL_MSB,
(request->u.ata.lba / (sectors * heads)) >> 8);
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(request->unit) |
(((request->u.ata.lba% (sectors * heads)) /
sectors) & 0xf));
}
else {
#endif
ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba);
ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
ATA_IDX_OUTB(ch, ATA_DRIVE,
ATA_D_IBM | ATA_D_LBA | ATA_DEV(request->unit) |
((request->u.ata.lba >> 24) & 0x0f));
#ifndef ATA_CAM
}
#endif
}
}

View File

@ -698,21 +698,6 @@ ata_pcichannel_resume(device_t dev)
return ata_resume(dev);
}
#ifndef ATA_CAM
static int
ata_pcichannel_locking(device_t dev, int mode)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
if (ctlr->locking)
return ctlr->locking(dev, mode);
else
return ch->unit;
}
#endif
static void
ata_pcichannel_reset(device_t dev)
{
@ -768,9 +753,6 @@ static device_method_t ata_pcichannel_methods[] = {
/* ATA methods */
DEVMETHOD(ata_setmode, ata_pcichannel_setmode),
DEVMETHOD(ata_getrev, ata_pcichannel_getrev),
#ifndef ATA_CAM
DEVMETHOD(ata_locking, ata_pcichannel_locking),
#endif
DEVMETHOD(ata_reset, ata_pcichannel_reset),
DEVMETHOD_END

View File

@ -62,9 +62,6 @@ struct ata_pci_controller {
int (*ch_detach)(device_t);
int (*ch_suspend)(device_t);
int (*ch_resume)(device_t);
#ifndef ATA_CAM
int (*locking)(device_t, int);
#endif
void (*reset)(device_t);
int (*setmode)(device_t, int, int);
int (*getrev)(device_t, int);

View File

@ -43,473 +43,6 @@ __FBSDID("$FreeBSD$");
#include <dev/ata/ata-all.h>
#include <ata_if.h>
#ifndef ATA_CAM
/* prototypes */
static void ata_completed(void *, int);
static void ata_sort_queue(struct ata_channel *ch, struct ata_request *request);
static const char *ata_skey2str(u_int8_t);
#endif
#ifndef ATA_CAM
void
ata_queue_request(struct ata_request *request)
{
struct ata_channel *ch;
struct ata_device *atadev = device_get_softc(request->dev);
/* treat request as virgin (this might be an ATA_R_REQUEUE) */
request->result = request->status = request->error = 0;
/* Prepare paramers required by low-level code. */
request->unit = atadev->unit;
if (!(request->parent = device_get_parent(request->dev))) {
request->result = ENXIO;
if (request->callback)
(request->callback)(request);
return;
}
if ((atadev->param.config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16)
request->flags |= ATA_R_ATAPI16;
if ((atadev->param.config & ATA_DRQ_MASK) == ATA_DRQ_INTR)
request->flags |= ATA_R_ATAPI_INTR;
if ((request->flags & ATA_R_ATAPI) == 0)
ata_modify_if_48bit(request);
ch = device_get_softc(request->parent);
callout_init_mtx(&request->callout, &ch->state_mtx, CALLOUT_RETURNUNLOCKED);
if (!request->callback && !(request->flags & ATA_R_REQUEUE))
sema_init(&request->done, 0, "ATA request done");
/* in ATA_STALL_QUEUE state we call HW directly */
if ((ch->state & ATA_STALL_QUEUE) && (request->flags & ATA_R_CONTROL)) {
mtx_lock(&ch->state_mtx);
ch->running = request;
if (ch->hw.begin_transaction(request) == ATA_OP_FINISHED) {
ch->running = NULL;
if (!request->callback)
sema_destroy(&request->done);
mtx_unlock(&ch->state_mtx);
return;
}
mtx_unlock(&ch->state_mtx);
}
/* otherwise put request on the locked queue at the specified location */
else {
mtx_lock(&ch->queue_mtx);
if (request->flags & ATA_R_AT_HEAD)
TAILQ_INSERT_HEAD(&ch->ata_queue, request, chain);
else if (request->flags & ATA_R_ORDERED)
ata_sort_queue(ch, request);
else
TAILQ_INSERT_TAIL(&ch->ata_queue, request, chain);
mtx_unlock(&ch->queue_mtx);
ATA_DEBUG_RQ(request, "queued");
ata_start(ch->dev);
}
/* if this is a requeued request callback/sleep we're done */
if (request->flags & ATA_R_REQUEUE)
return;
/* if this is not a callback wait until request is completed */
if (!request->callback) {
ATA_DEBUG_RQ(request, "wait for completion");
if (!dumping &&
sema_timedwait(&request->done, request->timeout * hz * 4)) {
callout_drain(&request->callout);
device_printf(request->dev,
"WARNING - %s taskqueue timeout "
"- completing request directly\n",
ata_cmd2str(request));
request->flags |= ATA_R_DANGER1;
ata_completed(request, 0);
}
sema_destroy(&request->done);
}
}
#endif
#ifndef ATA_CAM
int
ata_controlcmd(device_t dev, u_int8_t command, u_int16_t feature,
u_int64_t lba, u_int16_t count)
{
struct ata_device *atadev = device_get_softc(dev);
struct ata_request *request = ata_alloc_request();
int error = ENOMEM;
if (request) {
request->dev = dev;
request->u.ata.command = command;
request->u.ata.lba = lba;
request->u.ata.count = count;
request->u.ata.feature = feature;
request->flags = ATA_R_CONTROL;
if (atadev->spindown_state) {
device_printf(dev, "request while spun down, starting.\n");
atadev->spindown_state = 0;
request->timeout = MAX(ATA_REQUEST_TIMEOUT, 31);
} else {
request->timeout = ATA_REQUEST_TIMEOUT;
}
request->retries = 0;
ata_queue_request(request);
error = request->result;
ata_free_request(request);
}
return error;
}
#endif
#ifndef ATA_CAM
int
ata_atapicmd(device_t dev, u_int8_t *ccb, caddr_t data,
int count, int flags, int timeout)
{
struct ata_request *request = ata_alloc_request();
int error = ENOMEM;
if (request) {
request->dev = dev;
bcopy(ccb, request->u.atapi.ccb, 16);
request->data = data;
request->bytecount = count;
request->transfersize = min(request->bytecount, 65534);
request->flags = flags | ATA_R_ATAPI;
request->timeout = timeout;
request->retries = 0;
ata_queue_request(request);
error = request->result;
ata_free_request(request);
}
return error;
}
#endif
#ifndef ATA_CAM
void
ata_start(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
struct ata_request *request;
struct ata_composite *cptr;
int dependencies = 0;
/* if we have a request on the queue try to get it running */
mtx_lock(&ch->queue_mtx);
if ((request = TAILQ_FIRST(&ch->ata_queue))) {
/* we need the locking function to get the lock for this channel */
if (ATA_LOCKING(dev, ATA_LF_LOCK) == ch->unit) {
/* check for composite dependencies */
if ((cptr = request->composite)) {
mtx_lock(&cptr->lock);
if ((request->flags & ATA_R_WRITE) &&
(cptr->wr_depend & cptr->rd_done) != cptr->wr_depend) {
dependencies = 1;
}
mtx_unlock(&cptr->lock);
}
/* check we are in the right state and has no dependencies */
mtx_lock(&ch->state_mtx);
if (ch->state == ATA_IDLE && !dependencies) {
ATA_DEBUG_RQ(request, "starting");
TAILQ_REMOVE(&ch->ata_queue, request, chain);
ch->running = request;
ch->state = ATA_ACTIVE;
/* if we are the freezing point release it */
if (ch->freezepoint == request)
ch->freezepoint = NULL;
if (ch->hw.begin_transaction(request) == ATA_OP_FINISHED) {
ch->running = NULL;
ch->state = ATA_IDLE;
mtx_unlock(&ch->state_mtx);
mtx_unlock(&ch->queue_mtx);
ATA_LOCKING(dev, ATA_LF_UNLOCK);
ata_finish(request);
return;
}
}
mtx_unlock(&ch->state_mtx);
}
}
mtx_unlock(&ch->queue_mtx);
if (dumping) {
while (ch->running) {
ata_interrupt(ch);
DELAY(10);
}
}
}
#endif
#ifndef ATA_CAM
void
ata_finish(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(request->parent);
/*
* if in ATA_STALL_QUEUE state or request has ATA_R_DIRECT flags set
* we need to call ata_complete() directly here (no taskqueue involvement)
*/
if (dumping ||
(ch->state & ATA_STALL_QUEUE) || (request->flags & ATA_R_DIRECT)) {
ATA_DEBUG_RQ(request, "finish directly");
ata_completed(request, 0);
}
else {
/* put request on the proper taskqueue for completion */
if (request->bio && !(request->flags & (ATA_R_THREAD | ATA_R_TIMEOUT))){
ATA_DEBUG_RQ(request, "finish bio_taskqueue");
bio_taskqueue(request->bio, (bio_task_t *)ata_completed, request);
}
else {
TASK_INIT(&request->task, 0, ata_completed, request);
ATA_DEBUG_RQ(request, "finish taskqueue_swi");
taskqueue_enqueue(taskqueue_swi, &request->task);
}
}
}
#endif
#ifndef ATA_CAM
static void
ata_completed(void *context, int dummy)
{
struct ata_request *request = (struct ata_request *)context;
struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
struct ata_composite *composite;
if (request->flags & ATA_R_DANGER2) {
device_printf(request->dev,
"WARNING - %s freeing taskqueue zombie request\n",
ata_cmd2str(request));
request->flags &= ~(ATA_R_DANGER1 | ATA_R_DANGER2);
ata_free_request(request);
return;
}
if (request->flags & ATA_R_DANGER1)
request->flags |= ATA_R_DANGER2;
ATA_DEBUG_RQ(request, "completed entered");
/* if we had a timeout, reinit channel and deal with the falldown */
if (request->flags & ATA_R_TIMEOUT) {
/*
* if the channel is still present and
* reinit succeeds and
* the device doesn't get detached and
* there are retries left we reinject this request
*/
if (ch && !ata_reinit(ch->dev) && !request->result &&
(request->retries-- > 0)) {
if (!(request->flags & ATA_R_QUIET)) {
device_printf(request->dev,
"TIMEOUT - %s retrying (%d retr%s left)",
ata_cmd2str(request), request->retries,
request->retries == 1 ? "y" : "ies");
if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
printf(" LBA=%ju", request->u.ata.lba);
printf("\n");
}
request->flags &= ~(ATA_R_TIMEOUT | ATA_R_DEBUG);
request->flags |= (ATA_R_AT_HEAD | ATA_R_REQUEUE);
ATA_DEBUG_RQ(request, "completed reinject");
ata_queue_request(request);
return;
}
/* ran out of good intentions so finish with error */
if (!request->result) {
if (!(request->flags & ATA_R_QUIET)) {
if (request->dev) {
device_printf(request->dev, "FAILURE - %s timed out",
ata_cmd2str(request));
if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
printf(" LBA=%ju", request->u.ata.lba);
printf("\n");
}
}
request->result = EIO;
}
}
else if (!(request->flags & ATA_R_ATAPI) ){
/* if this is a soft ECC error warn about it */
/* XXX SOS we could do WARF here */
if ((request->status & (ATA_S_CORR | ATA_S_ERROR)) == ATA_S_CORR) {
device_printf(request->dev,
"WARNING - %s soft error (ECC corrected)",
ata_cmd2str(request));
if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
printf(" LBA=%ju", request->u.ata.lba);
printf("\n");
}
/* if this is a UDMA CRC error we reinject if there are retries left */
if (request->flags & ATA_R_DMA && request->error & ATA_E_ICRC) {
if (request->retries-- > 0) {
device_printf(request->dev,
"WARNING - %s UDMA ICRC error (retrying request)",
ata_cmd2str(request));
if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
printf(" LBA=%ju", request->u.ata.lba);
printf("\n");
request->flags |= (ATA_R_AT_HEAD | ATA_R_REQUEUE);
ata_queue_request(request);
return;
}
}
}
switch (request->flags & ATA_R_ATAPI) {
/* ATA errors */
default:
if (!request->result && request->status & ATA_S_ERROR) {
if (!(request->flags & ATA_R_QUIET)) {
device_printf(request->dev,
"FAILURE - %s status=%b error=%b",
ata_cmd2str(request),
request->status, "\20\10BUSY\7READY\6DMA_READY"
"\5DSC\4DRQ\3CORRECTABLE\2INDEX\1ERROR",
request->error, "\20\10ICRC\7UNCORRECTABLE"
"\6MEDIA_CHANGED\5NID_NOT_FOUND"
"\4MEDIA_CHANGE_REQEST"
"\3ABORTED\2NO_MEDIA\1ILLEGAL_LENGTH");
if ((request->flags & ATA_R_DMA) && request->dma &&
(request->dma->status & ATA_BMSTAT_ERROR))
printf(" dma=0x%02x", request->dma->status);
if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
printf(" LBA=%ju", request->u.ata.lba);
printf("\n");
}
request->result = EIO;
}
break;
/* ATAPI errors */
case ATA_R_ATAPI:
/* skip if result already set */
if (request->result)
break;
/* if we have a sensekey -> request sense from device */
if ((request->error & ATA_E_ATAPI_SENSE_MASK) &&
(request->u.atapi.ccb[0] != ATAPI_REQUEST_SENSE)) {
static u_int8_t ccb[16] = { ATAPI_REQUEST_SENSE, 0, 0, 0,
sizeof(struct atapi_sense),
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
request->u.atapi.saved_cmd = request->u.atapi.ccb[0];
bcopy(ccb, request->u.atapi.ccb, 16);
request->data = (caddr_t)&request->u.atapi.sense;
request->bytecount = sizeof(struct atapi_sense);
request->donecount = 0;
request->transfersize = sizeof(struct atapi_sense);
request->timeout = ATA_REQUEST_TIMEOUT;
request->flags &= (ATA_R_ATAPI | ATA_R_QUIET | ATA_R_DEBUG);
request->flags |= (ATA_R_READ | ATA_R_AT_HEAD | ATA_R_REQUEUE);
ATA_DEBUG_RQ(request, "autoissue request sense");
ata_queue_request(request);
return;
}
switch (request->u.atapi.sense.key & ATA_SENSE_KEY_MASK) {
case ATA_SENSE_RECOVERED_ERROR:
device_printf(request->dev, "WARNING - %s recovered error\n",
ata_cmd2str(request));
/* FALLTHROUGH */
case ATA_SENSE_NO_SENSE:
request->result = 0;
break;
case ATA_SENSE_NOT_READY:
request->result = EBUSY;
break;
case ATA_SENSE_UNIT_ATTENTION:
atadev->flags |= ATA_D_MEDIA_CHANGED;
request->result = EIO;
break;
default:
request->result = EIO;
if (request->flags & ATA_R_QUIET)
break;
device_printf(request->dev,
"FAILURE - %s %s asc=0x%02x ascq=0x%02x ",
ata_cmd2str(request), ata_skey2str(
(request->u.atapi.sense.key & ATA_SENSE_KEY_MASK)),
request->u.atapi.sense.asc,
request->u.atapi.sense.ascq);
if (request->u.atapi.sense.specific & ATA_SENSE_SPEC_VALID)
printf("sks=0x%02x 0x%02x 0x%02x\n",
request->u.atapi.sense.specific & ATA_SENSE_SPEC_MASK,
request->u.atapi.sense.specific1,
request->u.atapi.sense.specific2);
else
printf("\n");
}
if (!request->result &&
(request->u.atapi.sense.key & ATA_SENSE_KEY_MASK ||
request->error))
request->result = EIO;
}
ATA_DEBUG_RQ(request, "completed callback/wakeup");
/* if we are part of a composite operation we need to maintain progress */
if ((composite = request->composite)) {
int index = 0;
mtx_lock(&composite->lock);
/* update whats done */
if (request->flags & ATA_R_READ)
composite->rd_done |= (1 << request->this);
if (request->flags & ATA_R_WRITE)
composite->wr_done |= (1 << request->this);
/* find ready to go dependencies */
if (composite->wr_depend &&
(composite->rd_done & composite->wr_depend)==composite->wr_depend &&
(composite->wr_needed & (~composite->wr_done))) {
index = composite->wr_needed & ~composite->wr_done;
}
mtx_unlock(&composite->lock);
/* if we have any ready candidates kick them off */
if (index) {
int bit;
for (bit = 0; bit < MAX_COMPOSITES; bit++) {
if (index & (1 << bit))
ata_start(device_get_parent(composite->request[bit]->dev));
}
}
}
/* get results back to the initiator for this request */
if (request->callback)
(request->callback)(request);
else
sema_post(&request->done);
/* only call ata_start if channel is present */
if (ch)
ata_start(ch->dev);
}
#endif
void
ata_timeout(struct ata_request *request)
{
@ -530,160 +63,14 @@ ata_timeout(struct ata_request *request)
ch->dma.unload(request);
ch->running = NULL;
ch->state = ATA_IDLE;
#ifdef ATA_CAM
ata_cam_end_transaction(ch->dev, request);
#endif
mtx_unlock(&ch->state_mtx);
#ifndef ATA_CAM
ATA_LOCKING(ch->dev, ATA_LF_UNLOCK);
ata_finish(request);
#endif
}
else {
mtx_unlock(&ch->state_mtx);
}
}
#ifndef ATA_CAM
void
ata_fail_requests(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_request *request, *tmp;
TAILQ_HEAD(, ata_request) fail_requests;
TAILQ_INIT(&fail_requests);
/* grap all channel locks to avoid races */
mtx_lock(&ch->queue_mtx);
mtx_lock(&ch->state_mtx);
/* do we have any running request to care about ? */
if ((request = ch->running) && (!dev || request->dev == dev)) {
callout_stop(&request->callout);
ch->running = NULL;
request->result = ENXIO;
TAILQ_INSERT_TAIL(&fail_requests, request, chain);
}
/* fail all requests queued on this channel for device dev if !NULL */
TAILQ_FOREACH_SAFE(request, &ch->ata_queue, chain, tmp) {
if (!dev || request->dev == dev) {
TAILQ_REMOVE(&ch->ata_queue, request, chain);
request->result = ENXIO;
TAILQ_INSERT_TAIL(&fail_requests, request, chain);
}
}
mtx_unlock(&ch->state_mtx);
mtx_unlock(&ch->queue_mtx);
/* finish up all requests collected above */
TAILQ_FOREACH_SAFE(request, &fail_requests, chain, tmp) {
TAILQ_REMOVE(&fail_requests, request, chain);
ata_finish(request);
}
}
#endif
#ifndef ATA_CAM
/*
* Rudely drop all requests queued to the channel of specified device.
* XXX: The requests are leaked, use only in fatal case.
*/
void
ata_drop_requests(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_request *request, *tmp;
mtx_lock(&ch->queue_mtx);
TAILQ_FOREACH_SAFE(request, &ch->ata_queue, chain, tmp) {
TAILQ_REMOVE(&ch->ata_queue, request, chain);
request->result = ENXIO;
}
mtx_unlock(&ch->queue_mtx);
}
#endif
#ifndef ATA_CAM
static u_int64_t
ata_get_lba(struct ata_request *request)
{
if (request->flags & ATA_R_ATAPI) {
switch (request->u.atapi.ccb[0]) {
case ATAPI_READ_BIG:
case ATAPI_WRITE_BIG:
case ATAPI_READ_CD:
return (request->u.atapi.ccb[5]) | (request->u.atapi.ccb[4]<<8) |
(request->u.atapi.ccb[3]<<16)|(request->u.atapi.ccb[2]<<24);
case ATAPI_READ:
case ATAPI_WRITE:
return (request->u.atapi.ccb[4]) | (request->u.atapi.ccb[3]<<8) |
(request->u.atapi.ccb[2]<<16);
default:
return 0;
}
}
else
return request->u.ata.lba;
}
#endif
#ifndef ATA_CAM
static void
ata_sort_queue(struct ata_channel *ch, struct ata_request *request)
{
struct ata_request *this, *next;
this = TAILQ_FIRST(&ch->ata_queue);
/* if the queue is empty just insert */
if (!this) {
if (request->composite)
ch->freezepoint = request;
TAILQ_INSERT_TAIL(&ch->ata_queue, request, chain);
return;
}
/* dont sort frozen parts of the queue */
if (ch->freezepoint)
this = ch->freezepoint;
/* if position is less than head we add after tipping point */
if (ata_get_lba(request) < ata_get_lba(this)) {
while ((next = TAILQ_NEXT(this, chain))) {
/* have we reached the tipping point */
if (ata_get_lba(next) < ata_get_lba(this)) {
/* sort the insert */
do {
if (ata_get_lba(request) < ata_get_lba(next))
break;
this = next;
} while ((next = TAILQ_NEXT(this, chain)));
break;
}
this = next;
}
}
/* we are after head so sort the insert before tipping point */
else {
while ((next = TAILQ_NEXT(this, chain))) {
if (ata_get_lba(next) < ata_get_lba(this) ||
ata_get_lba(request) < ata_get_lba(next))
break;
this = next;
}
}
if (request->composite)
ch->freezepoint = request;
TAILQ_INSERT_AFTER(&ch->ata_queue, this, request, chain);
}
#endif
const char *
ata_cmd2str(struct ata_request *request)
{
@ -797,29 +184,3 @@ ata_cmd2str(struct ata_request *request)
sprintf(buffer, "unknown CMD (0x%02x)", request->u.ata.command);
return buffer;
}
#ifndef ATA_CAM
static const char *
ata_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");
}
}
#endif

View File

@ -1,333 +0,0 @@
/*-
* Copyright (c) 2008 Scott Long
* 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.
*
* 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$
*/
#ifndef ATA_RAID_DDF_H
#define ATA_RAID_DDF_H
/* Definitions from the SNIA DDF spec, rev 1.2 */
#define DDF_HEADER_LENGTH 512
struct ddf_header {
uint32_t Signature;
#define DDF_HEADER_SIGNATURE 0xde11de11
uint32_t CRC;
uint8_t DDF_Header_GUID[24];
uint8_t DDF_rev[8];
uint32_t Sequence_Number;
uint32_t TimeStamp;
uint8_t Open_Flag;
#define DDF_HEADER_CLOSED 0x00
#define DDF_HEADER_OPENED_MASK 0x0f
#define DDF_HEADER_OPEN_ANCHOR 0xff
uint8_t Foreign_Flag;
uint8_t Diskgrouping;
uint8_t pad1[13];
uint8_t Header_ext[32];
uint64_t Primary_Header_LBA;
uint64_t Secondary_Header_LBA;
uint8_t Header_Type;
#define DDF_HEADER_ANCHOR 0x00
#define DDF_HEADER_PRIMARY 0x01
#define DDF_HEADER_SECONDARY 0x02
uint8_t pad2[3];
uint32_t WorkSpace_Length;
uint64_t WorkSpace_LBA;
uint16_t Max_PD_Entries;
uint16_t Max_VD_Entries;
uint16_t Max_Partitions;
uint16_t Configuration_Record_Length;
uint16_t Max_Primary_Element_Entries;
uint8_t pad3[54];
uint32_t cd_section; /* Controller_Data_Section */
uint32_t cd_length; /* Controller_Data_Section_Length */
uint32_t pdr_section; /* Physical_Drive_Records_Section */
uint32_t pdr_length; /* Physical_Drive_Records_Length */
uint32_t vdr_section; /* Virtual_Drive_Records_Section */
uint32_t vdr_length; /* Virtual_Drive_Records_Length */
uint32_t cr_section; /* Configuration_Records_Section */
uint32_t cr_length; /* Configuration_Records_Length */
uint32_t pdd_section; /* Physical_Drive_Data_Section */
uint32_t pdd_length; /* Physical_Drive_Data_Length */
uint32_t bbmlog_section; /* BBM_Log_Section */
uint32_t bbmlog_length; /* BBM_Log_Section_Length */
uint32_t Diagnostic_Space;
uint32_t Diagnostic_Space_Length;
uint32_t Vendor_Specific_Logs;
uint32_t Vendor_Specific_Logs_Length;
uint8_t pad4[256];
} __packed;
struct ddf_cd_record {
uint32_t Signature;
#define DDF_CONTROLLER_DATA_SIGNATURE 0xad111111
uint32_t CRC;
uint8_t Controller_GUID[24];
struct {
uint16_t Vendor_ID;
uint16_t Device_ID;
uint16_t SubVendor_ID;
uint16_t SubDevice_ID;
} Controller_Type __packed;
uint8_t Product_ID[16];
uint8_t pad1[8];
uint8_t Controller_Data[448];
} __packed;
struct ddf_device_scsi {
uint8_t Lun;
uint8_t Id;
uint8_t Channel;
uint8_t Path_Flags;
#define DDF_DEVICE_SCSI_FLAG_BROKEN (1 << 7)
} __packed;
struct ddf_device_sas {
uint64_t Initiator_Path;
} __packed;
union ddf_pathinfo {
struct {
struct ddf_device_scsi Path0;
struct ddf_device_scsi Path1;
uint8_t pad[10];
} __packed scsi;
struct {
struct ddf_device_sas Path0;
struct ddf_device_sas Path1;
uint8_t Path0_Flags;
uint8_t Path1_Flags;
#define DDF_DEVICE_SAS_FLAG_BROKEN (1 << 7)
} __packed sas;
} __packed;
struct ddf_pd_entry {
uint8_t PD_GUID[24];
uint32_t PD_Reference;
uint16_t PD_Type;
#define DDF_PDE_GUID_FORCE (1 << 0)
#define DDF_PDE_PARTICIPATING (1 << 1)
#define DDF_PDE_GLOBAL_SPARE (1 << 2)
#define DDF_PDE_CONFIG_SPARE (1 << 3)
#define DDF_PDE_FOREIGN (1 << 4)
#define DDF_PDE_LEGACY (1 << 5)
#define DDF_PDE_TYPE_MASK (0x0f << 12)
#define DDF_PDE_UNKNOWN (0x00 << 12)
#define DDF_PDE_SCSI (0x01 << 12)
#define DDF_PDE_SAS (0x02 << 12)
#define DDF_PDE_SATA (0x03 << 12)
#define DDF_PDE_FC (0x04 << 12)
uint16_t PD_State;
#define DDF_PDE_ONLINE (1 << 0)
#define DDF_PDE_FAILED (1 << 1)
#define DDF_PDE_REBUILD (1 << 2)
#define DDF_PDE_TRANSITION (1 << 3)
#define DDF_PDE_PFA (1 << 4)
#define DDF_PDE_UNRECOVERED (1 << 5)
#define DDF_PDE_MISSING (1 << 6)
uint64_t Configured_Size;
union ddf_pathinfo Path_Information;
uint8_t pad1[6];
} __packed;
struct ddf_pd_record {
uint32_t Signature;
#define DDF_PDR_SIGNATURE 0x22222222
uint32_t CRC;
uint16_t Populated_PDEs;
uint16_t Max_PDE_Supported;
uint8_t pad1[52];
struct ddf_pd_entry entry[0];
} __packed;
struct ddf_vd_entry {
uint8_t VD_GUID[24];
uint16_t VD_Number;
uint8_t pad1[2];
uint16_t VD_Type;
#define DDF_VDE_SHARED (1 << 0)
#define DDF_VDE_ENFORCE_GROUP (1 << 1)
#define DDF_VDE_UNICODE_NAME (1 << 2)
#define DDF_VDE_OWNER_ID_VALID (1 << 3)
uint16_t Controller_GUID_CRC;
uint8_t VD_State;
#define DDF_VDE_OPTIMAL 0x00
#define DDF_VDE_DEGRADED 0x01
#define DDF_VDE_DELETED 0x02
#define DDF_VDE_MISSING 0x03
#define DDF_VDE_FAILED 0x04
#define DDF_VDE_PARTIAL 0x05
#define DDF_VDE_STATE_MASK 0x07
#define DDF_VDE_MORPH (1 << 3)
#define DDF_VDE_DIRTY (1 << 4)
uint8_t Init_State;
#define DDF_VDE_UNINTIALIZED 0x00
#define DDF_VDE_INIT_QUICK 0x01
#define DDF_VDE_INIT_FULL 0x02
#define DDF_VDE_INIT_MASK 0x03
#define DDF_VDE_UACCESS_RW 0x00
#define DDF_VDE_UACCESS_RO 0x80
#define DDF_VDE_UACCESS_BLOCKED 0xc0
#define DDF_VDE_UACCESS_MASK 0xc0
uint8_t pad2[14];
uint8_t VD_Name[16];
} __packed;
struct ddf_vd_record {
uint32_t Signature;
#define DDF_VD_RECORD_SIGNATURE 0xdddddddd
uint32_t CRC;
uint16_t Populated_VDEs;
uint16_t Max_VDE_Supported;
uint8_t pad1[52];
struct ddf_vd_entry entry[0];
} __packed;
#define DDF_CR_INVALID 0xffffffff
struct ddf_vdc_record {
uint32_t Signature;
#define DDF_VDCR_SIGNATURE 0xeeeeeeee
uint32_t CRC;
uint8_t VD_GUID[24];
uint32_t Timestamp;
uint32_t Sequence_Number;
uint8_t pad1[24];
uint16_t Primary_Element_Count;
uint8_t Stripe_Size;
uint8_t Primary_RAID_Level;
#define DDF_VDCR_RAID0 0x00
#define DDF_VDCR_RAID1 0x01
#define DDF_VDCR_RAID3 0x03
#define DDF_VDCR_RAID4 0x04
#define DDF_VDCR_RAID5 0x05
#define DDF_VDCR_RAID6 0x06
#define DDF_VDCR_RAID1E 0x11
#define DDF_VDCR_SINGLE 0x0f
#define DDF_VDCR_CONCAT 0x1f
#define DDF_VDCR_RAID5E 0x15
#define DDF_VDCR_RAID5EE 0x25
uint8_t RLQ;
uint8_t Secondary_Element_Count;
uint8_t Secondary_Element_Seq;
uint8_t Secondary_RAID_Level;
uint64_t Block_Count;
uint64_t VD_Size;
uint8_t pad2[8];
uint32_t Associated_Spares[8];
uint64_t Cache_Flags;
#define DDF_VDCR_CACHE_WB (1 << 0)
#define DDF_VDCR_CACHE_WB_ADAPTIVE (1 << 1)
#define DDF_VDCR_CACHE_RA (1 << 2)
#define DDF_VDCR_CACHE_RA_ADAPTIVE (1 << 3)
#define DDF_VDCR_CACHE_WCACHE_NOBATTERY (1 << 4)
#define DDF_VDCR_CACHE_WCACHE_ALLOW (1 << 5)
#define DDF_VDCR_CACHE_RCACHE_ALLOW (1 << 6)
#define DDF_VDCR_CACHE_VENDOR (1 << 7)
uint8_t BG_Rate;
uint8_t pad3[3];
uint8_t pad4[52];
uint8_t pad5[192];
uint8_t V0[32];
uint8_t V1[32];
uint8_t V2[16];
uint8_t V3[16];
uint8_t Vendor_Scratch[32];
uint32_t Physical_Disk_Sequence[0];
} __packed;
struct ddf_vuc_record {
uint32_t Signature;
#define DDF_VUCR_SIGNATURE 0x88888888
uint32_t CRC;
uint8_t VD_GUID[24];
} __packed;
struct ddf_sa_entry {
uint8_t VD_GUID[24];
uint16_t Secondary_Element;
uint8_t rsrvd2[6];
} __packed;
struct ddf_sa_record {
uint32_t Signature;
#define DDF_SA_SIGNATURE 0x55555555
uint32_t CRC;
uint32_t Timestamp;
uint8_t pad1[7];
uint8_t Spare_Type;
#define DDF_SAR_TYPE_DEDICATED (1 << 0)
#define DDF_SAR_TYPE_REVERTIBLE (1 << 1)
#define DDF_SAR_TYPE_ACTIVE (1 << 2)
#define DDF_SAR_TYPE_ENCL_AFFINITY (1 << 3)
uint16_t Populated_SAEs;
uint16_t MAX_SAE_Supported;
uint8_t pad2[8];
struct ddf_sa_entry entry[0];
} __packed;
struct ddf_pdd_record {
uint32_t Signature;
#define DDF_PDD_SIGNATURE 0x33333333
uint32_t CRC;
uint8_t PD_GUID[24];
uint32_t PD_Reference;
uint8_t Forced_Ref_Flag;
#define DDF_PDD_FORCED_REF 0x01
uint8_t Forced_PD_GUID_Flag;
#define DDF_PDD_FORCED_GUID 0x01
uint8_t Vendor_Scratch[32];
uint8_t pad2[442];
} __packed;
struct ddf_bbm_entry {
uint64_t Defective_Block_Start;
uint32_t Spare_Block_Offset;
uint16_t Remapped_Count;
uint8_t pad[2];
};
struct ddf_bbm_log {
uint32_t Signature;
#define DDF_BBML_SIGNATURE 0xabadb10c
uint32_t CRC;
uint16_t Entry_Count;
uint32_t Spare_Block_Count;
uint8_t pad1[10];
uint64_t First_Spare_LBA;
uint64_t Mapped_Block_Entry[0];
} __packed;
struct ddf_vendor_log {
uint32_t Signature;
#define DDF_VENDOR_LOG_SIGNATURE 0x01dbeef0
uint32_t CRC;
uint64_t Log_Owner;
uint8_t pad1[16];
} __packed;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,817 +0,0 @@
/*-
* Copyright (c) 2000 - 2008 Søren Schmidt <sos@FreeBSD.org>
* 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.
*
* 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$
*/
/* misc defines */
#define MAX_ARRAYS 16
#define MAX_VOLUMES 4
#define MAX_DISKS 16
#define AR_PROXIMITY 2048 /* how many sectors is "close" */
#define ATA_MAGIC "FreeBSD ATA driver RAID "
struct ata_raid_subdisk {
struct ar_softc *raid[MAX_VOLUMES];
int disk_number[MAX_VOLUMES];
};
/* ATA PseudoRAID Metadata */
struct ar_softc {
int lun;
u_int8_t name[32];
int volume;
u_int64_t magic_0;
u_int64_t magic_1;
int type;
#define AR_T_JBOD 0x0001
#define AR_T_SPAN 0x0002
#define AR_T_RAID0 0x0004
#define AR_T_RAID1 0x0008
#define AR_T_RAID01 0x0010
#define AR_T_RAID3 0x0020
#define AR_T_RAID4 0x0040
#define AR_T_RAID5 0x0080
int status;
#define AR_S_READY 0x0001
#define AR_S_DEGRADED 0x0002
#define AR_S_REBUILDING 0x0004
int format;
#define AR_F_FREEBSD_RAID 0x0001
#define AR_F_ADAPTEC_RAID 0x0002
#define AR_F_HPTV2_RAID 0x0004
#define AR_F_HPTV3_RAID 0x0008
#define AR_F_INTEL_RAID 0x0010
#define AR_F_ITE_RAID 0x0020
#define AR_F_JMICRON_RAID 0x0040
#define AR_F_LSIV2_RAID 0x0080
#define AR_F_LSIV3_RAID 0x0100
#define AR_F_NVIDIA_RAID 0x0200
#define AR_F_PROMISE_RAID 0x0400
#define AR_F_SII_RAID 0x0800
#define AR_F_SIS_RAID 0x1000
#define AR_F_VIA_RAID 0x2000
#define AR_F_DDF_RAID 0x4000
#define AR_F_FORMAT_MASK 0x7fff
u_int generation;
u_int64_t total_sectors;
u_int64_t offset_sectors; /* offset from start of disk */
u_int16_t heads;
u_int16_t sectors;
u_int32_t cylinders;
u_int width; /* array width in disks */
u_int interleave; /* interleave in sectors */
u_int total_disks; /* number of disks in this array */
struct ar_disk {
device_t dev;
u_int8_t serial[16]; /* serial # of physical disk */
u_int64_t sectors; /* useable sectors on this disk */
off_t last_lba; /* last lba used (for performance) */
u_int flags;
#define AR_DF_PRESENT 0x0001 /* this HW pos has a disk present */
#define AR_DF_ASSIGNED 0x0002 /* this HW pos assigned to an array */
#define AR_DF_SPARE 0x0004 /* this HW pos is a spare */
#define AR_DF_ONLINE 0x0008 /* this HW pos is online and in use */
} disks[MAX_DISKS];
int toggle; /* performance hack for RAID1's */
u_int64_t rebuild_lba; /* rebuild progress indicator */
struct mtx lock; /* metadata lock */
struct disk *disk; /* disklabel/slice stuff */
struct proc *pid; /* rebuilder process id */
};
/* Adaptec HostRAID Metadata */
#define ADP_LBA(dev) \
(((struct ad_softc *)device_get_ivars(dev))->total_secs - 17)
/* note all entries are big endian */
struct adaptec_raid_conf {
u_int32_t magic_0;
#define ADP_MAGIC_0 0xc4650790
u_int32_t generation;
u_int16_t dummy_0;
u_int16_t total_configs;
u_int16_t dummy_1;
u_int16_t checksum;
u_int32_t dummy_2;
u_int32_t dummy_3;
u_int32_t flags;
u_int32_t timestamp;
u_int32_t dummy_4[4];
u_int32_t dummy_5[4];
struct {
u_int16_t total_disks;
u_int16_t generation;
u_int32_t magic_0;
u_int8_t dummy_0;
u_int8_t type;
#define ADP_T_RAID0 0x00
#define ADP_T_RAID1 0x01
u_int8_t dummy_1;
u_int8_t flags;
u_int8_t dummy_2;
u_int8_t dummy_3;
u_int8_t dummy_4;
u_int8_t dummy_5;
u_int32_t disk_number;
u_int32_t dummy_6;
u_int32_t sectors;
u_int16_t stripe_shift;
u_int16_t dummy_7;
u_int32_t dummy_8[4];
u_int8_t name[16];
} configs[127];
u_int32_t dummy_6[13];
u_int32_t magic_1;
#define ADP_MAGIC_1 0x9ff85009
u_int32_t dummy_7[3];
u_int32_t magic_2;
u_int32_t dummy_8[46];
u_int32_t magic_3;
#define ADP_MAGIC_3 0x4d545044
u_int32_t magic_4;
#define ADP_MAGIC_4 0x9ff85009
u_int32_t dummy_9[62];
} __packed;
/* DDF Information. Metadata definitions are in another file */
#define DDF_LBA(dev) \
(((struct ad_softc *)device_get_ivars(dev))->total_secs - 1)
/* Highpoint V2 RocketRAID Metadata */
#define HPTV2_LBA(dev) 9
struct hptv2_raid_conf {
int8_t filler1[32];
u_int32_t magic;
#define HPTV2_MAGIC_OK 0x5a7816f0
#define HPTV2_MAGIC_BAD 0x5a7816fd
u_int32_t magic_0;
u_int32_t magic_1;
u_int32_t order;
#define HPTV2_O_RAID0 0x01
#define HPTV2_O_RAID1 0x02
#define HPTV2_O_OK 0x04
u_int8_t array_width;
u_int8_t stripe_shift;
u_int8_t type;
#define HPTV2_T_RAID0 0x00
#define HPTV2_T_RAID1 0x01
#define HPTV2_T_RAID01_RAID0 0x02
#define HPTV2_T_SPAN 0x03
#define HPTV2_T_RAID_3 0x04
#define HPTV2_T_RAID_5 0x05
#define HPTV2_T_JBOD 0x06
#define HPTV2_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 HPTV2_R_REMOVED 0xfe
#define HPTV2_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];
} __packed;
/* Highpoint V3 RocketRAID Metadata */
#define HPTV3_LBA(dev) \
(((struct ad_softc *)device_get_ivars(dev))->total_secs - 11)
struct hptv3_raid_conf {
u_int32_t magic;
#define HPTV3_MAGIC 0x5a7816f3
u_int32_t magic_0;
u_int8_t checksum_0;
u_int8_t mode;
#define HPTV3_BOOT_MARK 0x01
#define HPTV3_USER_MODE 0x02
u_int8_t user_mode;
u_int8_t config_entries;
struct {
u_int32_t total_sectors;
u_int8_t type;
#define HPTV3_T_SPARE 0x00
#define HPTV3_T_JBOD 0x03
#define HPTV3_T_SPAN 0x04
#define HPTV3_T_RAID0 0x05
#define HPTV3_T_RAID1 0x06
#define HPTV3_T_RAID3 0x07
#define HPTV3_T_RAID5 0x08
u_int8_t total_disks;
u_int8_t disk_number;
u_int8_t stripe_shift;
u_int16_t status;
#define HPTV3_T_NEED_REBUILD 0x01
#define HPTV3_T_RAID5_FLAG 0x02
u_int16_t critical_disks;
u_int32_t rebuild_lba;
} __packed configs[2];
u_int8_t name[16];
u_int32_t timestamp;
u_int8_t description[64];
u_int8_t creator[16];
u_int8_t checksum_1;
u_int8_t dummy_0;
u_int8_t dummy_1;
u_int8_t flags;
#define HPTV3_T_ENABLE_TCQ 0x01
#define HPTV3_T_ENABLE_NCQ 0x02
#define HPTV3_T_ENABLE_WCACHE 0x04
#define HPTV3_T_ENABLE_RCACHE 0x08
struct {
u_int32_t total_sectors;
u_int32_t rebuild_lba;
} __packed configs_high[2];
u_int32_t filler[87];
} __packed;
/* Intel MatrixRAID Metadata */
#define INTEL_LBA(dev) \
(((struct ad_softc *)device_get_ivars(dev))->total_secs - 3)
struct intel_raid_conf {
u_int8_t intel_id[24];
#define INTEL_MAGIC "Intel Raid ISM Cfg Sig. "
u_int8_t version[6];
#define INTEL_VERSION_1100 "1.1.00"
#define INTEL_VERSION_1201 "1.2.01"
#define INTEL_VERSION_1202 "1.2.02"
u_int8_t dummy_0[2];
u_int32_t checksum;
u_int32_t config_size;
u_int32_t config_id;
u_int32_t generation;
u_int32_t dummy_1[2];
u_int8_t total_disks;
u_int8_t total_volumes;
u_int8_t dummy_2[2];
u_int32_t filler_0[39];
struct {
u_int8_t serial[16];
u_int32_t sectors;
u_int32_t id;
u_int32_t flags;
#define INTEL_F_SPARE 0x01
#define INTEL_F_ASSIGNED 0x02
#define INTEL_F_DOWN 0x04
#define INTEL_F_ONLINE 0x08
u_int32_t filler[5];
} __packed disk[1];
u_int32_t filler_1[62];
} __packed;
struct intel_raid_mapping {
u_int8_t name[16];
u_int64_t total_sectors __packed;
u_int32_t state;
u_int32_t reserved;
u_int32_t filler_0[20];
u_int32_t offset;
u_int32_t disk_sectors;
u_int32_t stripe_count;
u_int16_t stripe_sectors;
u_int8_t status;
#define INTEL_S_READY 0x00
#define INTEL_S_DISABLED 0x01
#define INTEL_S_DEGRADED 0x02
#define INTEL_S_FAILURE 0x03
u_int8_t type;
#define INTEL_T_RAID0 0x00
#define INTEL_T_RAID1 0x01
#define INTEL_T_RAID5 0x05
u_int8_t total_disks;
u_int8_t magic[3];
u_int32_t filler_1[7];
u_int32_t disk_idx[1];
} __packed;
/* Integrated Technology Express Metadata */
#define ITE_LBA(dev) \
(((struct ad_softc *)device_get_ivars(dev))->total_secs - 2)
struct ite_raid_conf {
u_int32_t filler_1[5];
u_int8_t timestamp_0[8];
u_int32_t dummy_1;
u_int32_t filler_2[5];
u_int16_t filler_3;
u_int8_t ite_id[40];
#define ITE_MAGIC "Integrated Technology Express Inc "
u_int16_t filler_4;
u_int32_t filler_5[6];
u_int32_t dummy_2;
u_int32_t dummy_3;
u_int32_t filler_6[12];
u_int32_t dummy_4;
u_int32_t filler_7[5];
u_int64_t total_sectors __packed;
u_int32_t filler_8[12];
u_int16_t filler_9;
u_int8_t type;
#define ITE_T_RAID0 0x00
#define ITE_T_RAID1 0x01
#define ITE_T_RAID01 0x02
#define ITE_T_SPAN 0x03
u_int8_t filler_10;
u_int32_t dummy_5[8];
u_int8_t stripe_1kblocks;
u_int8_t filler_11[3];
u_int32_t filler_12[54];
u_int32_t dummy_6[4];
u_int8_t timestamp_1[8];
u_int32_t filler_13[9];
u_int8_t stripe_sectors;
u_int8_t filler_14[3];
u_int8_t array_width;
u_int8_t filler_15[3];
u_int32_t filler_16;
u_int8_t filler_17;
u_int8_t disk_number;
u_int32_t disk_sectors;
u_int16_t filler_18;
u_int32_t dummy_7[4];
u_int32_t filler_20[104];
} __packed;
/* JMicron Technology Corp Metadata */
#define JMICRON_LBA(dev) \
(((struct ad_softc *)device_get_ivars(dev))->total_secs - 1)
#define JM_MAX_DISKS 8
struct jmicron_raid_conf {
u_int8_t signature[2];
#define JMICRON_MAGIC "JM"
u_int16_t version;
#define JMICRON_VERSION 0x0001
u_int16_t checksum;
u_int8_t filler_1[10];
u_int32_t disk_id;
u_int32_t offset;
u_int32_t disk_sectors_high;
u_int16_t disk_sectors_low;
u_int8_t filler_2[2];
u_int8_t name[16];
u_int8_t type;
#define JM_T_RAID0 0
#define JM_T_RAID1 1
#define JM_T_RAID01 2
#define JM_T_JBOD 3
#define JM_T_RAID5 5
u_int8_t stripe_shift;
u_int16_t flags;
#define JM_F_READY 0x0001
#define JM_F_BOOTABLE 0x0002
#define JM_F_BAD 0x0004
#define JM_F_ACTIVE 0c0010
#define JM_F_UNSYNC 0c0020
#define JM_F_NEWEST 0c0040
u_int8_t filler_3[4];
u_int32_t spare[2];
u_int32_t disks[JM_MAX_DISKS];
u_int8_t filler_4[32];
u_int8_t filler_5[384];
};
/* LSILogic V2 MegaRAID Metadata */
#define LSIV2_LBA(dev) \
(((struct ad_softc *)device_get_ivars(dev))->total_secs - 1)
struct lsiv2_raid_conf {
u_int8_t lsi_id[6];
#define LSIV2_MAGIC "$XIDE$"
u_int8_t dummy_0;
u_int8_t flags;
u_int16_t version;
u_int8_t config_entries;
u_int8_t raid_count;
u_int8_t total_disks;
u_int8_t dummy_1;
u_int16_t dummy_2;
union {
struct {
u_int8_t type;
#define LSIV2_T_RAID0 0x01
#define LSIV2_T_RAID1 0x02
#define LSIV2_T_SPARE 0x08
u_int8_t dummy_0;
u_int16_t stripe_sectors;
u_int8_t array_width;
u_int8_t disk_count;
u_int8_t config_offset;
u_int8_t dummy_1;
u_int8_t flags;
#define LSIV2_R_DEGRADED 0x02
u_int32_t total_sectors;
u_int8_t filler[3];
} __packed raid;
struct {
u_int8_t device;
#define LSIV2_D_MASTER 0x00
#define LSIV2_D_SLAVE 0x01
#define LSIV2_D_CHANNEL0 0x00
#define LSIV2_D_CHANNEL1 0x10
#define LSIV2_D_NONE 0xff
u_int8_t dummy_0;
u_int32_t disk_sectors;
u_int8_t disk_number;
u_int8_t raid_number;
u_int8_t flags;
#define LSIV2_D_GONE 0x02
u_int8_t filler[7];
} __packed disk;
} configs[30];
u_int8_t disk_number;
u_int8_t raid_number;
u_int32_t timestamp;
u_int8_t filler[10];
} __packed;
/* LSILogic V3 MegaRAID Metadata */
#define LSIV3_LBA(dev) \
(((struct ad_softc *)device_get_ivars(dev))->total_secs - 4)
struct lsiv3_raid_conf {
u_int32_t magic_0; /* 0xa0203200 */
u_int32_t filler_0[3];
u_int8_t magic_1[4]; /* "SATA" */
u_int32_t filler_1[40];
u_int32_t dummy_0; /* 0x0d000003 */
u_int32_t filler_2[7];
u_int32_t dummy_1; /* 0x0d000003 */
u_int32_t filler_3[70];
u_int8_t magic_2[8]; /* "$_ENQ$31" */
u_int8_t filler_4[7];
u_int8_t checksum_0;
u_int8_t filler_5[512*2];
u_int8_t lsi_id[6];
#define LSIV3_MAGIC "$_IDE$"
u_int16_t dummy_2; /* 0x33de for OK disk */
u_int16_t version; /* 0x0131 for this version */
u_int16_t dummy_3; /* 0x0440 always */
u_int32_t filler_6;
struct {
u_int16_t stripe_pages;
u_int8_t type;
#define LSIV3_T_RAID0 0x00
#define LSIV3_T_RAID1 0x01
u_int8_t dummy_0;
u_int8_t total_disks;
u_int8_t array_width;
u_int8_t filler_0[10];
u_int32_t sectors;
u_int16_t dummy_1;
u_int32_t offset;
u_int16_t dummy_2;
u_int8_t device;
#define LSIV3_D_DEVICE 0x01
#define LSIV3_D_CHANNEL 0x10
u_int8_t dummy_3;
u_int8_t dummy_4;
u_int8_t dummy_5;
u_int8_t filler_1[16];
} __packed raid[8];
struct {
u_int32_t disk_sectors;
u_int32_t dummy_0;
u_int32_t dummy_1;
u_int8_t dummy_2;
u_int8_t dummy_3;
u_int8_t flags;
#define LSIV3_D_MIRROR 0x00
#define LSIV3_D_STRIPE 0xff
u_int8_t dummy_4;
} __packed disk[6];
u_int8_t filler_7[7];
u_int8_t device;
u_int32_t timestamp;
u_int8_t filler_8[3];
u_int8_t checksum_1;
} __packed;
/* nVidia MediaShield Metadata */
#define NVIDIA_LBA(dev) \
(((struct ad_softc *)device_get_ivars(dev))->total_secs - 2)
struct nvidia_raid_conf {
u_int8_t nvidia_id[8];
#define NV_MAGIC "NVIDIA "
u_int32_t config_size;
u_int32_t checksum;
u_int16_t version;
u_int8_t disk_number;
u_int8_t dummy_0;
u_int32_t total_sectors;
u_int32_t sector_size;
u_int8_t serial[16];
u_int8_t revision[4];
u_int32_t dummy_1;
u_int32_t magic_0;
#define NV_MAGIC0 0x00640044
u_int64_t magic_1;
u_int64_t magic_2;
u_int8_t flags;
u_int8_t array_width;
u_int8_t total_disks;
u_int8_t dummy_2;
u_int16_t type;
#define NV_T_RAID0 0x00000080
#define NV_T_RAID1 0x00000081
#define NV_T_RAID3 0x00000083
#define NV_T_RAID5 0x00000085
#define NV_T_RAID01 0x00008180
#define NV_T_SPAN 0x000000ff
u_int16_t dummy_3;
u_int32_t stripe_sectors;
u_int32_t stripe_bytes;
u_int32_t stripe_shift;
u_int32_t stripe_mask;
u_int32_t stripe_sizesectors;
u_int32_t stripe_sizebytes;
u_int32_t rebuild_lba;
u_int32_t dummy_4;
u_int32_t dummy_5;
u_int32_t status;
#define NV_S_BOOTABLE 0x00000001
#define NV_S_DEGRADED 0x00000002
u_int32_t filler[98];
} __packed;
/* Promise FastTrak Metadata */
#define PROMISE_LBA(dev) \
(((((struct ad_softc *)device_get_ivars(dev))->total_secs / (((struct ad_softc *)device_get_ivars(dev))->heads * ((struct ad_softc *)device_get_ivars(dev))->sectors)) * ((struct ad_softc *)device_get_ivars(dev))->heads * ((struct ad_softc *)device_get_ivars(dev))->sectors) - ((struct ad_softc *)device_get_ivars(dev))->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) (((u_int64_t)(x.channel) << 48) | \
((u_int64_t)(x.device != 0) << 56))
u_int16_t magic_1;
u_int32_t magic_2;
u_int8_t filler1[470];
struct {
u_int32_t integrity;
#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 __packed;
u_int32_t disk_offset;
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
#define PR_T_JBOD 0x10
u_int8_t total_disks;
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;
u_int64_t magic_1 __packed;
struct {
u_int8_t flags;
u_int8_t dummy_0;
u_int8_t channel;
u_int8_t device;
u_int64_t magic_0 __packed;
} disk[8];
} raid;
int32_t filler2[346];
u_int32_t checksum;
} __packed;
/* Silicon Image Medley Metadata */
#define SII_LBA(dev) \
( ((struct ad_softc *)device_get_ivars(dev))->total_secs - 1)
struct sii_raid_conf {
u_int16_t ata_params_00_53[54];
u_int64_t total_sectors;
u_int16_t ata_params_58_79[70];
u_int16_t dummy_0;
u_int16_t dummy_1;
u_int32_t controller_pci_id;
u_int16_t version_minor;
u_int16_t version_major;
u_int8_t timestamp[6];
u_int16_t stripe_sectors;
u_int16_t dummy_2;
u_int8_t disk_number;
u_int8_t type;
#define SII_T_RAID0 0x00
#define SII_T_RAID1 0x01
#define SII_T_RAID01 0x02
#define SII_T_SPARE 0x03
u_int8_t raid0_disks;
u_int8_t raid0_ident;
u_int8_t raid1_disks;
u_int8_t raid1_ident;
u_int64_t rebuild_lba;
u_int32_t generation;
u_int8_t status;
#define SII_S_READY 0x01
u_int8_t base_raid1_position;
u_int8_t base_raid0_position;
u_int8_t position;
u_int16_t dummy_3;
u_int8_t name[16];
u_int16_t checksum_0;
int8_t filler1[190];
u_int16_t checksum_1;
} __packed;
/* Silicon Integrated Systems RAID Metadata */
#define SIS_LBA(dev) \
( ((struct ad_softc *)device_get_ivars(dev))->total_secs - 16)
struct sis_raid_conf {
u_int16_t magic;
#define SIS_MAGIC 0x0010
u_int8_t disks;
#define SIS_D_MASTER 0xf0
#define SIS_D_MIRROR 0x0f
u_int8_t type_total_disks;
#define SIS_D_MASK 0x0f
#define SIS_T_MASK 0xf0
#define SIS_T_JBOD 0x10
#define SIS_T_RAID0 0x20
#define SIS_T_RAID1 0x30
u_int32_t dummy_0;
u_int32_t controller_pci_id;
u_int16_t stripe_sectors;
u_int16_t dummy_1;
u_int32_t timestamp;
u_int8_t model[40];
u_int8_t disk_number;
u_int8_t dummy_2[3];
int8_t filler1[448];
} __packed;
/* VIA Tech V-RAID Metadata */
#define VIA_LBA(dev) \
( ((struct ad_softc *)device_get_ivars(dev))->total_secs - 1)
struct via_raid_conf {
u_int16_t magic;
#define VIA_MAGIC 0xaa55
u_int8_t dummy_0;
u_int8_t type;
#define VIA_T_MASK 0x7e
#define VIA_T_BOOTABLE 0x01
#define VIA_T_RAID0 0x04
#define VIA_T_RAID1 0x0c
#define VIA_T_RAID01 0x4c
#define VIA_T_RAID5 0x2c
#define VIA_T_SPAN 0x44
#define VIA_T_UNKNOWN 0x80
u_int8_t disk_index;
#define VIA_D_MASK 0x0f
#define VIA_D_DEGRADED 0x10
#define VIA_D_HIGH_IDX 0x20
u_int8_t stripe_layout;
#define VIA_L_DISKS 0x07
#define VIA_L_MASK 0xf0
#define VIA_L_SHIFT 4
u_int64_t disk_sectors;
u_int32_t disk_id;
u_int32_t disks[8];
u_int8_t checksum;
u_int8_t filler_1[461];
} __packed;

View File

@ -157,13 +157,9 @@ ata_sata_phy_reset(device_t dev, int port, int quick)
int loop, retry, sata_rev;
uint32_t val, val1;
#ifdef ATA_CAM
sata_rev = ch->user[port < 0 ? 0 : port].revision;
if (sata_rev > 0)
quick = 0;
#else
sata_rev = 0;
#endif
if (quick) {
if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))

View File

@ -38,24 +38,6 @@
INTERFACE ata;
CODE {
static int ata_null_locking(device_t dev, int mode)
{
struct ata_channel *ch = device_get_softc(dev);
return ch->unit;
}
};
METHOD int locking {
device_t channel;
int mode;
} DEFAULT ata_null_locking;
HEADER {
#define ATA_LF_LOCK 0x0001
#define ATA_LF_UNLOCK 0x0002
#define ATA_LF_WHICH 0x0004
};
CODE {
static int ata_null_setmode(device_t dev, int target, int mode)
{

View File

@ -1,919 +0,0 @@
/*-
* Copyright (c) 2001-2007 Thomas Quinot <thomas@cuivre.fr.eu.org>
* 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/ata.h>
#include <sys/taskqueue.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sema.h>
#include <vm/uma.h>
#include <machine/resource.h>
#include <machine/bus.h>
#include <cam/cam.h>
#include <cam/cam_ccb.h>
#include <cam/cam_periph.h>
#include <cam/cam_sim.h>
#include <cam/cam_xpt_sim.h>
#include <cam/cam_debug.h>
#include <cam/scsi/scsi_all.h>
#include <dev/ata/ata-all.h>
#include <ata_if.h>
/* private data associated with an ATA bus */
struct atapi_xpt_softc {
struct ata_device atapi_cam_dev; /* must be first */
device_t dev;
device_t parent;
struct ata_channel *ata_ch;
struct cam_path *path;
struct cam_sim *sim;
int flags;
#define BUS_REGISTERED 0x01
#define RESOURCE_SHORTAGE 0x02
#define DETACHING 0x04
TAILQ_HEAD(,atapi_hcb) pending_hcbs;
struct ata_device *atadev[2];
struct mtx state_lock;
};
/* hardware command descriptor block */
struct atapi_hcb {
struct atapi_xpt_softc *softc;
int unit;
int bus;
int target;
int lun;
union ccb *ccb;
int flags;
#define QUEUED 0x0001
#define AUTOSENSE 0x0002
char *dxfer_alloc;
TAILQ_ENTRY(atapi_hcb) chain;
};
enum reinit_reason { BOOT_ATTACH, ATTACH, RESET };
/* Device methods */
static void atapi_cam_identify(driver_t *dev, device_t parent);
static int atapi_cam_probe(device_t dev);
static int atapi_cam_attach(device_t dev);
static int atapi_cam_detach(device_t dev);
static int atapi_cam_reinit(device_t dev);
/* 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_cb(struct ata_request *);
/* Module methods */
static int atapi_cam_event_handler(module_t mod, int what, void *arg);
/* internal functions */
static void reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason);
static void setup_async_cb(struct atapi_xpt_softc *, uint32_t);
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 MALLOC_DEFINE(M_ATACAM, "ata_cam", "ATA driver CAM-XPT layer");
static device_method_t atapi_cam_methods[] = {
DEVMETHOD(device_identify, atapi_cam_identify),
DEVMETHOD(device_probe, atapi_cam_probe),
DEVMETHOD(device_attach, atapi_cam_attach),
DEVMETHOD(device_detach, atapi_cam_detach),
DEVMETHOD(ata_reinit, atapi_cam_reinit),
DEVMETHOD_END
};
static driver_t atapi_cam_driver = {
"atapicam",
atapi_cam_methods,
sizeof(struct atapi_xpt_softc)
};
static devclass_t atapi_cam_devclass;
DRIVER_MODULE(atapicam, ata,
atapi_cam_driver,
atapi_cam_devclass,
atapi_cam_event_handler,
/*arg*/NULL);
MODULE_VERSION(atapicam, 1);
MODULE_DEPEND(atapicam, ata, 1, 1, 1);
MODULE_DEPEND(atapicam, cam, 1, 1, 1);
static void
atapi_cam_identify(driver_t *driver, device_t parent)
{
struct atapi_xpt_softc *scp =
malloc (sizeof (struct atapi_xpt_softc), M_ATACAM, M_NOWAIT|M_ZERO);
device_t child;
if (scp == NULL) {
printf ("atapi_cam_identify: out of memory");
return;
}
/* Assume one atapicam instance per parent channel instance. */
child = device_add_child(parent, "atapicam", -1);
if (child == NULL) {
printf ("atapi_cam_identify: out of memory, can't add child");
free (scp, M_ATACAM);
return;
}
scp->atapi_cam_dev.unit = -1;
scp->atapi_cam_dev.dev = child;
device_quiet(child);
device_set_softc(child, scp);
}
static int
atapi_cam_probe(device_t dev)
{
struct ata_device *atadev = device_get_softc (dev);
KASSERT(atadev != NULL, ("expect valid struct ata_device"));
if (atadev->unit < 0) {
device_set_desc(dev, "ATAPI CAM Attachment");
return (0);
} else {
return ENXIO;
}
}
static int
atapi_cam_attach(device_t dev)
{
struct atapi_xpt_softc *scp = NULL;
struct cam_devq *devq = NULL;
struct cam_sim *sim = NULL;
struct cam_path *path = NULL;
int unit, error;
scp = (struct atapi_xpt_softc *)device_get_softc(dev);
if (scp == NULL) {
device_printf(dev, "Cannot get softc\n");
return (ENOMEM);
}
mtx_init(&scp->state_lock, "ATAPICAM lock", NULL, MTX_DEF);
scp->dev = dev;
scp->parent = device_get_parent(dev);
scp->ata_ch = device_get_softc(scp->parent);
TAILQ_INIT(&scp->pending_hcbs);
unit = device_get_unit(device_get_parent(dev));
if ((devq = cam_simq_alloc(16)) == NULL) {
error = ENOMEM;
goto out;
}
if ((sim = cam_sim_alloc(atapi_action, atapi_poll, "ata",
(void *)scp, unit, &scp->state_lock, 1, 1, devq)) == NULL) {
error = ENOMEM;
goto out;
}
scp->sim = sim;
mtx_lock(&scp->state_lock);
if (xpt_bus_register(sim, dev, 0) != CAM_SUCCESS) {
error = EINVAL;
mtx_unlock(&scp->state_lock);
goto out;
}
scp->flags |= BUS_REGISTERED;
if (xpt_create_path(&path, /*periph*/ NULL,
cam_sim_path(sim), CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
error = ENOMEM;
mtx_unlock(&scp->state_lock);
goto out;
}
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, cold ? BOOT_ATTACH : ATTACH);
error = 0;
mtx_unlock(&scp->state_lock);
out:
if (error != 0)
free_softc(scp);
return (error);
}
static int
atapi_cam_detach(device_t dev)
{
struct atapi_xpt_softc *scp = device_get_softc(dev);
mtx_lock(&scp->state_lock);
if (xpt_sim_opened(scp->sim)) {
mtx_unlock(&scp->state_lock);
return (EBUSY);
}
xpt_freeze_simq(scp->sim, 1 /*count*/);
scp->flags |= DETACHING;
mtx_unlock(&scp->state_lock);
free_softc(scp);
return (0);
}
static int
atapi_cam_reinit(device_t dev) {
struct atapi_xpt_softc *scp = device_get_softc(dev);
/*
* scp might be null if the bus is being reinitialised during
* the boot-up sequence, before the ATAPI bus is registered.
*/
if (scp != NULL) {
mtx_lock(&scp->state_lock);
reinit_bus(scp, RESET);
mtx_unlock(&scp->state_lock);
}
return (0);
}
static void
reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason) {
struct ata_device *old_atadev[2], *atadev;
device_t *children;
int nchildren, i, dev_changed;
if (device_get_children(scp->parent, &children, &nchildren) != 0) {
return;
}
old_atadev[0] = scp->atadev[0];
old_atadev[1] = scp->atadev[1];
scp->atadev[0] = NULL;
scp->atadev[1] = NULL;
for (i = 0; i < nchildren; i++) {
/* XXX Does the child need to actually be attached yet? */
if (children[i] != NULL) {
atadev = device_get_softc(children[i]);
if ((atadev->unit == ATA_MASTER) &&
(scp->ata_ch->devices & ATA_ATAPI_MASTER) != 0)
scp->atadev[0] = atadev;
if ((atadev->unit == ATA_SLAVE) &&
(scp->ata_ch->devices & ATA_ATAPI_SLAVE) != 0)
scp->atadev[1] = atadev;
}
}
dev_changed = (old_atadev[0] != scp->atadev[0])
|| (old_atadev[1] != scp->atadev[1]);
free(children, M_TEMP);
switch (reason) {
case BOOT_ATTACH:
case ATTACH:
break;
case RESET:
xpt_async(AC_BUS_RESET, scp->path, NULL);
if (!dev_changed)
break;
cam_rescan(scp->sim);
break;
}
}
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;
struct ata_request *request = 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;
int tid = ccb_h->target_id;
cpi->version_num = 1;
cpi->hba_inquiry = 0;
cpi->target_sprt = 0;
cpi->hba_misc = PIM_NO_6_BYTE;
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_SPI;
cpi->transport_version = 2;
cpi->protocol = PROTO_SCSI;
cpi->protocol_version = SCSI_REV_2;
if (softc->ata_ch && tid != CAM_TARGET_WILDCARD) {
if (softc->atadev[tid] == NULL) {
ccb->ccb_h.status = CAM_DEV_NOT_THERE;
xpt_done(ccb);
return;
}
switch (softc->atadev[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;
case ATA_SA150:
cpi->base_transfer_speed = 150000;
break;
case ATA_SA300:
cpi->base_transfer_speed = 300000;
break;
default:
break;
}
}
cpi->maxio = softc->ata_ch->dma.max_iosize ?
softc->ata_ch->dma.max_iosize : DFLTPHYS;
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
return;
}
case XPT_RESET_DEV: {
int tid = ccb_h->target_id;
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("dev reset\n"));
mtx_unlock(&softc->state_lock);
ata_controlcmd(softc->atadev[tid]->dev, ATA_DEVICE_RESET, 0, 0, 0);
mtx_lock(&softc->state_lock);
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"));
mtx_unlock(&softc->state_lock);
ata_reinit(softc->parent);
mtx_lock(&softc->state_lock);
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_SPI;
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: {
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("CALC_GEOMETRY\n"));
cam_calc_geometry(&ccb->ccg, /*extended*/1);
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;
int request_flags = ATA_R_ATAPI;
CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE, ("XPT_SCSI_IO\n"));
if (softc->flags & DETACHING) {
ccb->ccb_h.status = CAM_REQ_ABORTED;
xpt_done(ccb);
return;
}
if (softc->atadev[tid] == NULL) {
ccb->ccb_h.status = CAM_DEV_NOT_THERE;
xpt_done(ccb);
return;
}
/* check that this request was not aborted already */
if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
printf("XPT_SCSI_IO received but already in progress?\n");
xpt_done(ccb);
return;
}
if (lid > 0) {
CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE,
("SCSI IO received for invalid lun %d\n", lid));
goto action_invalid;
}
if (csio->cdb_len > sizeof request->u.atapi.ccb) {
CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE,
("CAM CCB too long for ATAPI"));
goto action_invalid;
}
switch (ccb_h->flags & CAM_DIR_MASK) {
case CAM_DIR_IN:
request_flags |= ATA_R_READ;
break;
case CAM_DIR_OUT:
request_flags |= ATA_R_WRITE;
break;
case CAM_DIR_NONE:
/* No flags need to be set */
break;
default:
device_printf(softc->dev, "unknown IO operation\n");
goto action_invalid;
}
if ((hcb = allocate_hcb(softc, unit, bus, ccb)) == NULL) {
printf("cannot allocate ATAPI/CAM hcb\n");
goto action_oom;
}
if ((request = ata_alloc_request()) == NULL) {
printf("cannot allocate ATAPI/CAM request\n");
goto action_oom;
}
bcopy((ccb_h->flags & CAM_CDB_POINTER) ?
csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes,
request->u.atapi.ccb, csio->cdb_len);
#ifdef CAMDEBUG
if (CAM_DEBUGGED(ccb_h->path, CAM_DEBUG_CDB)) {
char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
printf("atapi_action: hcb@%p: %s\n", hcb,
scsi_cdb_string(request->u.atapi.ccb, cdb_str, sizeof(cdb_str)));
}
if (CAM_DEBUGGED(ccb_h->path, CAM_DEBUG_SUBTRACE)) {
request_flags |= ATA_R_DEBUG;
}
#endif
len = csio->dxfer_len;
buf = csio->data_ptr;
/* some SCSI commands require special processing */
switch (request->u.atapi.ccb[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 *) &request->u.atapi.ccb[0];
if (inq->byte2 == 0 && inq->page_code == 0 &&
scsi_2btoul(inq->length) > SHORT_INQUIRY_LENGTH) {
bzero(buf, len);
len = SHORT_INQUIRY_LENGTH;
scsi_ulto2b(len, inq->length);
}
break;
}
case READ_6:
/* FALLTHROUGH */
case WRITE_6:
CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE,
("Translating %s into _10 equivalent\n",
(request->u.atapi.ccb[0] == READ_6) ? "READ_6" : "WRITE_6"));
request->u.atapi.ccb[0] |= 0x20;
request->u.atapi.ccb[9] = request->u.atapi.ccb[5];
request->u.atapi.ccb[8] = request->u.atapi.ccb[4];
request->u.atapi.ccb[7] = 0;
request->u.atapi.ccb[6] = 0;
request->u.atapi.ccb[5] = request->u.atapi.ccb[3];
request->u.atapi.ccb[4] = request->u.atapi.ccb[2];
request->u.atapi.ccb[3] = request->u.atapi.ccb[1] & 0x1f;
request->u.atapi.ccb[2] = 0;
request->u.atapi.ccb[1] = 0;
/* FALLTHROUGH */
case READ_10:
/* FALLTHROUGH */
case WRITE_10:
/* FALLTHROUGH */
case READ_12:
/* FALLTHROUGH */
case WRITE_12:
/*
* Enable DMA (if target supports it) for READ and WRITE commands
* only, as some combinations of drive, controller and chipset do
* not behave correctly when DMA is enabled for other commands.
*/
if (softc->atadev[tid]->mode >= ATA_DMA)
request_flags |= ATA_R_DMA;
break;
}
if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_IN && (len & 1)) {
/* ATA always transfers an even number of bytes */
if ((buf = hcb->dxfer_alloc
= malloc(++len, M_ATACAM, M_NOWAIT | M_ZERO)) == NULL) {
printf("cannot allocate ATAPI/CAM buffer\n");
goto action_oom;
}
}
request->dev = softc->atadev[tid]->dev;
request->driver = hcb;
request->data = buf;
request->bytecount = len;
request->transfersize = min(request->bytecount, 65534);
request->timeout = (ccb_h->timeout + 999) / 1000;
request->callback = &atapi_cb;
request->flags = request_flags;
/*
* no retries are to be performed at the ATA level; any retries
* will be done by CAM.
*/
request->retries = 0;
TAILQ_INSERT_TAIL(&softc->pending_hcbs, hcb, chain);
hcb->flags |= QUEUED;
ccb_h->status |= CAM_SIM_QUEUED;
mtx_unlock(&softc->state_lock);
ata_queue_request(request);
mtx_lock(&softc->state_lock);
return;
}
default:
CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE,
("unsupported function code 0x%02x\n", ccb_h->func_code));
goto action_invalid;
}
/* NOTREACHED */
action_oom:
if (request != NULL)
ata_free_request(request);
if (hcb != NULL)
free_hcb(hcb);
xpt_print_path(ccb_h->path);
printf("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);
return;
action_invalid:
ccb_h->status = CAM_REQ_INVALID;
xpt_done(ccb);
return;
}
static void
atapi_poll(struct cam_sim *sim)
{
struct atapi_xpt_softc *softc =
(struct atapi_xpt_softc*)cam_sim_softc(sim);
mtx_unlock(&softc->state_lock);
ata_interrupt(softc->ata_ch);
mtx_lock(&softc->state_lock);
}
static void
atapi_cb(struct ata_request *request)
{
struct atapi_xpt_softc *scp;
struct atapi_hcb *hcb;
struct ccb_scsiio *csio;
u_int32_t rc;
hcb = (struct atapi_hcb *)request->driver;
scp = hcb->softc;
csio = &hcb->ccb->csio;
#ifdef CAMDEBUG
# define err (request->u.atapi.sense.key)
if (CAM_DEBUGGED(csio->ccb_h.path, CAM_DEBUG_CDB)) {
printf("atapi_cb: hcb@%p sense = %02x: sk = %01x%s%s%s\n",
hcb, err, err & 0x0f,
(err & 0x80) ? ", Filemark" : "",
(err & 0x40) ? ", EOM" : "",
(err & 0x20) ? ", ILI" : "");
device_printf(request->dev,
"cmd %s status %02x result %02x error %02x\n",
ata_cmd2str(request),
request->status, request->result, request->error);
}
#endif
if ((hcb->flags & AUTOSENSE) != 0) {
rc = CAM_SCSI_STATUS_ERROR;
if (request->result == 0) {
csio->ccb_h.status |= CAM_AUTOSNS_VALID;
}
} else if (request->result != 0) {
if ((request->flags & ATA_R_TIMEOUT) != 0) {
rc = CAM_CMD_TIMEOUT;
} else {
rc = CAM_SCSI_STATUS_ERROR;
csio->scsi_status = SCSI_STATUS_CHECK_COND;
if ((csio->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) {
#if 0
static const int8_t ccb[16] = { ATAPI_REQUEST_SENSE, 0, 0, 0,
sizeof(struct atapi_sense), 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0 };
bcopy (ccb, request->u.atapi.ccb, sizeof ccb);
request->data = (caddr_t)&csio->sense_data;
request->bytecount = sizeof(struct atapi_sense);
request->transfersize = min(request->bytecount, 65534);
request->timeout = (csio->ccb_h.timeout + 999) / 1000;
request->retries = 2;
request->flags = ATA_R_QUIET|ATA_R_ATAPI|ATA_R_IMMEDIATE;
hcb->flags |= AUTOSENSE;
ata_queue_request(request);
return;
#else
/*
* Use auto-sense data from the ATA layer, if it has
* issued a REQUEST SENSE automatically and that operation
* returned without error.
*/
if (request->u.atapi.sense.key != 0 && request->error == 0) {
bcopy (&request->u.atapi.sense, &csio->sense_data, sizeof(struct atapi_sense));
csio->ccb_h.status |= CAM_AUTOSNS_VALID;
}
}
#endif
}
} else {
rc = CAM_REQ_CMP;
csio->scsi_status = SCSI_STATUS_OK;
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);
}
}
mtx_lock(&scp->state_lock);
free_hcb_and_ccb_done(hcb, rc);
mtx_unlock(&scp->state_lock);
ata_free_request(request);
}
static void
free_hcb_and_ccb_done(struct atapi_hcb *hcb, u_int32_t status)
{
struct atapi_xpt_softc *softc;
union ccb *ccb;
if (hcb == NULL)
return;
softc = hcb->softc;
ccb = hcb->ccb;
/* 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)
{
int targ;
GIANT_REQUIRED;
switch (code) {
case AC_LOST_DEVICE:
targ = xpt_path_target_id(path);
xpt_print_path(path);
if (targ == -1)
printf("Lost host adapter\n");
else
printf("Lost target %d???\n", targ);
break;
default:
break;
}
}
static void
cam_rescan(struct cam_sim *sim)
{
union ccb *ccb;
ccb = xpt_alloc_ccb_nowait();
if (ccb == NULL)
return;
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(sim),
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
xpt_free_ccb(ccb);
return;
}
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("Rescanning ATAPI bus.\n"));
xpt_rescan(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 = (struct atapi_hcb *)
malloc(sizeof(struct atapi_hcb), M_ATACAM, M_NOWAIT | 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)
{
if ((hcb->flags & QUEUED) != 0)
TAILQ_REMOVE(&hcb->softc->pending_hcbs, hcb, chain);
if (hcb->dxfer_alloc != NULL)
free(hcb->dxfer_alloc, M_ATACAM);
free(hcb, M_ATACAM);
}
static void
free_softc(struct atapi_xpt_softc *scp)
{
struct atapi_hcb *hcb, *thcb;
if (scp != NULL) {
mtx_lock(&scp->state_lock);
TAILQ_FOREACH_SAFE(hcb, &scp->pending_hcbs, chain, thcb) {
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, /*free_devq*/TRUE);
else
printf("Can't free %s SIM (still registered)\n",
cam_sim_name(scp->sim));
}
mtx_destroy(&scp->state_lock);
}
}
static int
atapi_cam_event_handler(module_t mod, int what, void *arg) {
device_t *devlist;
int devcount;
switch (what) {
case MOD_UNLOAD:
if (devclass_get_devices(atapi_cam_devclass, &devlist, &devcount)
!= 0)
return ENXIO;
if (devlist != NULL) {
while (devlist != NULL && devcount > 0) {
device_t child = devlist[--devcount];
struct atapi_xpt_softc *scp = device_get_softc(child);
device_delete_child(device_get_parent(child),child);
if (scp != NULL)
free(scp, M_ATACAM);
}
free(devlist, M_TEMP);
}
break;
default:
break;
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,315 +0,0 @@
/*-
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* 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.
*
* 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$
*/
/* 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_DVD 0x40
#define MST_NO_DISC 0x70
#define MST_DOOR_OPEN 0x71
#define MST_FMT_ERROR 0x72
u_int8_t dev_spec;
u_int16_t unused;
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_int16_t media;
#define MST_READ_CDR 0x0100
#define MST_READ_CDRW 0x0200
#define MST_READ_PACKET 0x0400
#define MST_READ_DVDROM 0x0800
#define MST_READ_DVDR 0x1000
#define MST_READ_DVDRAM 0x2000
#define MST_WRITE_CDR 0x0001
#define MST_WRITE_CDRW 0x0002
#define MST_WRITE_TEST 0x0004
#define MST_WRITE_DVDR 0x0010
#define MST_WRITE_DVDRAM 0x0020
u_int16_t capabilities;
#define MST_AUDIO_PLAY 0x0100
#define MST_COMPOSITE 0x0200
#define MST_AUDIO_P1 0x0400
#define MST_AUDIO_P2 0x0800
#define MST_MODE2_f1 0x1000
#define MST_MODE2_f2 0x2000
#define MST_MULTISESSION 0x4000
#define MST_BURNPROOF 0x8000
#define MST_READ_CDDA 0x0001
#define MST_CDDA_STREAM 0x0002
#define MST_COMBINED_RW 0x0004
#define MST_CORRECTED_RW 0x0008
#define MST_SUPPORT_C2 0x0010
#define MST_ISRC 0x0020
#define MST_UPC 0x0040
u_int8_t mechanism;
#define MST_LOCKABLE 0x01
#define MST_LOCKED 0x02
#define MST_PREVENT 0x04
#define MST_EJECT 0x08
#define MST_MECH_MASK 0xe0
#define MST_MECH_CADDY 0x00
#define MST_MECH_TRAY 0x20
#define MST_MECH_POPUP 0x40
#define MST_MECH_CHANGER 0x80
#define MST_MECH_CARTRIDGE 0xa0
uint8_t audio;
#define MST_SEP_VOL 0x01
#define MST_SEP_MUTE 0x02
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 misc;
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;
};
#define CH_READY 0
#define CH_LOADING 1
#define CH_UNLOADING 2
#define CH_INITIALIZING 3
#define CD_IDLE 0
#define CD_AUDIO_ACTIVE 1
#define CD_AUDIO_SCAN 2
#define CD_HOST_ACTIVE 3
#define CD_NO_STATE 7
/* 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 */
u_int8_t fault :1; /* fault in last operation */
u_int8_t reserved0 :5;
u_int8_t cd_state :3; /* current mechanism state */
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 link_size_valid :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 link_size;
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;
} __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 */
};
/* Structure describing an ATAPI CDROM device */
struct acd_softc {
int flags; /* device state flags */
#define F_LOCKED 0x0001 /* this unit is locked */
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 */
u_int32_t disk_size; /* size of current media */
u_int32_t block_size; /* blocksize currently used */
u_int32_t iomax; /* Max I/O request (bytes) */
struct g_geom *gp; /* geom instance */
struct g_provider *pp[MAXTRK+1]; /* providers */
};

View File

@ -1,440 +0,0 @@
/*-
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* 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.
*
* 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ata.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/cdio.h>
#include <sys/sema.h>
#include <sys/taskqueue.h>
#include <vm/uma.h>
#include <machine/bus.h>
#include <geom/geom_disk.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/atapi-fd.h>
#include <ata_if.h>
/* prototypes */
static disk_open_t afd_open;
static disk_close_t afd_close;
static disk_strategy_t afd_strategy;
static disk_ioctl_t afd_ioctl;
static int afd_sense(device_t);
static void afd_describe(device_t);
static void afd_done(struct ata_request *);
static int afd_prevent_allow(device_t, int);
static int afd_test_ready(device_t);
/* internal vars */
static MALLOC_DEFINE(M_AFD, "afd_driver", "ATAPI floppy driver buffers");
static int
afd_probe(device_t dev)
{
struct ata_device *atadev = device_get_softc(dev);
if ((atadev->param.config & ATA_PROTO_ATAPI) &&
(atadev->param.config & ATA_ATAPI_TYPE_MASK) == ATA_ATAPI_TYPE_DIRECT)
return 0;
else
return ENXIO;
}
static int
afd_attach(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
struct afd_softc *fdp;
if (!(fdp = malloc(sizeof(struct afd_softc), M_AFD, M_NOWAIT | M_ZERO))) {
device_printf(dev, "out of memory\n");
return ENOMEM;
}
device_set_ivars(dev, fdp);
ata_setmode(dev);
if (afd_sense(dev)) {
device_set_ivars(dev, NULL);
free(fdp, M_AFD);
return ENXIO;
}
atadev->flags |= ATA_D_MEDIA_CHANGED;
/* announce we are here */
afd_describe(dev);
/* create the disk device */
fdp->disk = disk_alloc();
fdp->disk->d_open = afd_open;
fdp->disk->d_close = afd_close;
fdp->disk->d_strategy = afd_strategy;
fdp->disk->d_ioctl = afd_ioctl;
fdp->disk->d_name = "afd";
fdp->disk->d_drv1 = dev;
fdp->disk->d_maxsize = ch->dma.max_iosize ? ch->dma.max_iosize : DFLTPHYS;
fdp->disk->d_unit = device_get_unit(dev);
disk_create(fdp->disk, DISK_VERSION);
return 0;
}
static int
afd_detach(device_t dev)
{
struct afd_softc *fdp = device_get_ivars(dev);
/* check that we have a valid device to detach */
if (!device_get_ivars(dev))
return ENXIO;
/* detroy disk from the system so we dont get any further requests */
disk_destroy(fdp->disk);
/* fail requests on the queue and any thats "in flight" for this device */
ata_fail_requests(dev);
/* dont leave anything behind */
device_set_ivars(dev, NULL);
free(fdp, M_AFD);
return 0;
}
static int
afd_shutdown(device_t dev)
{
struct ata_device *atadev = device_get_softc(dev);
if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
ata_controlcmd(dev, ATA_FLUSHCACHE, 0, 0, 0);
return 0;
}
static int
afd_reinit(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
/* if detach pending, return error */
if (!(ch->devices & (ATA_ATAPI_MASTER << atadev->unit)))
return 1;
ata_setmode(dev);
return 0;
}
static int
afd_open(struct disk *dp)
{
device_t dev = dp->d_drv1;
struct ata_device *atadev = device_get_softc(dev);
struct afd_softc *fdp = device_get_ivars(dev);
if (!fdp)
return ENXIO;
if (!device_is_attached(dev))
return EBUSY;
afd_test_ready(dev);
afd_prevent_allow(dev, 1);
if (afd_sense(dev))
device_printf(dev, "sense media type failed\n");
atadev->flags &= ~ATA_D_MEDIA_CHANGED;
if (!fdp->mediasize)
return ENXIO;
fdp->disk->d_sectorsize = fdp->sectorsize;
fdp->disk->d_mediasize = fdp->mediasize;
fdp->disk->d_fwsectors = fdp->sectors;
fdp->disk->d_fwheads = fdp->heads;
return 0;
}
static int
afd_close(struct disk *dp)
{
device_t dev = dp->d_drv1;
afd_prevent_allow(dev, 0);
return 0;
}
static void
afd_strategy(struct bio *bp)
{
device_t dev = bp->bio_disk->d_drv1;
struct ata_device *atadev = device_get_softc(dev);
struct afd_softc *fdp = device_get_ivars(dev);
struct ata_request *request;
u_int16_t count;
int8_t ccb[16];
/* if it's a null transfer, return immediatly. */
if (bp->bio_bcount == 0) {
bp->bio_resid = 0;
biodone(bp);
return;
}
/* should reject all queued entries if media have changed. */
if (atadev->flags & ATA_D_MEDIA_CHANGED) {
biofinish(bp, NULL, EIO);
return;
}
count = bp->bio_bcount / fdp->sectorsize;
bp->bio_resid = bp->bio_bcount;
bzero(ccb, sizeof(ccb));
if (bp->bio_cmd == BIO_READ)
ccb[0] = ATAPI_READ_BIG;
else
ccb[0] = ATAPI_WRITE_BIG;
ccb[2] = bp->bio_pblkno >> 24;
ccb[3] = bp->bio_pblkno >> 16;
ccb[4] = bp->bio_pblkno >> 8;
ccb[5] = bp->bio_pblkno;
ccb[7] = count>>8;
ccb[8] = count;
if (!(request = ata_alloc_request())) {
biofinish(bp, NULL, ENOMEM);
return;
}
request->dev = dev;
request->bio = bp;
bcopy(ccb, request->u.atapi.ccb, 16);
request->data = bp->bio_data;
request->bytecount = count * fdp->sectorsize;
request->transfersize = min(request->bytecount, 65534);
request->timeout = (ccb[0] == ATAPI_WRITE_BIG) ? 60 : 30;
request->retries = 2;
request->callback = afd_done;
switch (bp->bio_cmd) {
case BIO_READ:
request->flags = (ATA_R_ATAPI | ATA_R_READ);
break;
case BIO_WRITE:
request->flags = (ATA_R_ATAPI | ATA_R_WRITE);
break;
default:
device_printf(dev, "unknown BIO operation\n");
ata_free_request(request);
biofinish(bp, NULL, EIO);
return;
}
if (atadev->mode >= ATA_DMA)
request->flags |= ATA_R_DMA;
request->flags |= ATA_R_ORDERED;
ata_queue_request(request);
}
static void
afd_done(struct ata_request *request)
{
struct bio *bp = request->bio;
/* finish up transfer */
if ((bp->bio_error = request->result))
bp->bio_flags |= BIO_ERROR;
bp->bio_resid = bp->bio_bcount - request->donecount;
biodone(bp);
ata_free_request(request);
}
static int
afd_ioctl(struct disk *disk, u_long cmd, void *data, int flag,struct thread *td)
{
return ata_device_ioctl(disk->d_drv1, cmd, data);
}
static int
afd_sense(device_t dev)
{
struct ata_device *atadev = device_get_softc(dev);
struct afd_softc *fdp = device_get_ivars(dev);
struct afd_capacity capacity;
struct afd_capacity_big capacity_big;
struct afd_capabilities capabilities;
int8_t ccb1[16] = { ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
int8_t ccb2[16] = { ATAPI_SERVICE_ACTION_IN, 0x10, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, sizeof(struct afd_capacity_big) & 0xff, 0, 0 };
int8_t ccb3[16] = { ATAPI_MODE_SENSE_BIG, 0, ATAPI_REWRITEABLE_CAP_PAGE,
0, 0, 0, 0, sizeof(struct afd_capabilities) >> 8,
sizeof(struct afd_capabilities) & 0xff,
0, 0, 0, 0, 0, 0, 0 };
int timeout = 20;
int error, count;
fdp->mediasize = 0;
/* wait for device to get ready */
while ((error = afd_test_ready(dev)) && timeout--) {
DELAY(100000);
}
if (error == EBUSY)
return 1;
/* The IOMEGA Clik! doesn't support reading the cap page, fake it */
if (!strncmp(atadev->param.model, "IOMEGA Clik!", 12)) {
fdp->heads = 1;
fdp->sectors = 2;
fdp->mediasize = 39441 * 1024;
fdp->sectorsize = 512;
afd_test_ready(dev);
return 0;
}
/* get drive capacity */
if (!ata_atapicmd(dev, ccb1, (caddr_t)&capacity,
sizeof(struct afd_capacity), ATA_R_READ, 30)) {
fdp->heads = 16;
fdp->sectors = 63;
fdp->sectorsize = be32toh(capacity.blocksize);
fdp->mediasize = (u_int64_t)be32toh(capacity.capacity)*fdp->sectorsize;
afd_test_ready(dev);
return 0;
}
/* get drive capacity big */
if (!ata_atapicmd(dev, ccb2, (caddr_t)&capacity_big,
sizeof(struct afd_capacity_big),
ATA_R_READ | ATA_R_QUIET, 30)) {
fdp->heads = 16;
fdp->sectors = 63;
fdp->sectorsize = be32toh(capacity_big.blocksize);
fdp->mediasize = be64toh(capacity_big.capacity)*fdp->sectorsize;
afd_test_ready(dev);
return 0;
}
/* get drive capabilities, some bugridden drives needs this repeated */
for (count = 0 ; count < 5 ; count++) {
if (!ata_atapicmd(dev, ccb3, (caddr_t)&capabilities,
sizeof(struct afd_capabilities), ATA_R_READ, 30) &&
capabilities.page_code == ATAPI_REWRITEABLE_CAP_PAGE) {
fdp->heads = capabilities.heads;
fdp->sectors = capabilities.sectors;
fdp->sectorsize = be16toh(capabilities.sector_size);
fdp->mediasize = be16toh(capabilities.cylinders) *
fdp->heads * fdp->sectors * fdp->sectorsize;
if (!capabilities.medium_type)
fdp->mediasize = 0;
return 0;
}
}
return 1;
}
static int
afd_prevent_allow(device_t dev, int lock)
{
struct ata_device *atadev = device_get_softc(dev);
int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
if (!strncmp(atadev->param.model, "IOMEGA Clik!", 12))
return 0;
return ata_atapicmd(dev, ccb, NULL, 0, 0, 30);
}
static int
afd_test_ready(device_t dev)
{
int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
return ata_atapicmd(dev, ccb, NULL, 0, 0, 30);
}
static void
afd_describe(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
struct afd_softc *fdp = device_get_ivars(dev);
char sizestring[16];
if (fdp->mediasize > 1048576 * 5)
sprintf(sizestring, "%juMB", fdp->mediasize / 1048576);
else if (fdp->mediasize)
sprintf(sizestring, "%juKB", fdp->mediasize / 1024);
else
strcpy(sizestring, "(no media)");
device_printf(dev, "%s <%.40s %.8s> at ata%d-%s %s %s\n",
sizestring, atadev->param.model, atadev->param.revision,
device_get_unit(ch->dev), ata_unit2str(atadev),
ata_mode2str(atadev->mode),
ata_satarev2str(ATA_GETREV(device_get_parent(dev), atadev->unit)));
if (bootverbose) {
device_printf(dev, "%ju sectors [%juC/%dH/%dS]\n",
fdp->mediasize / fdp->sectorsize,
fdp->mediasize /(fdp->sectorsize*fdp->sectors*fdp->heads),
fdp->heads, fdp->sectors);
}
}
static device_method_t afd_methods[] = {
/* device interface */
DEVMETHOD(device_probe, afd_probe),
DEVMETHOD(device_attach, afd_attach),
DEVMETHOD(device_detach, afd_detach),
DEVMETHOD(device_shutdown, afd_shutdown),
/* ATA methods */
DEVMETHOD(ata_reinit, afd_reinit),
DEVMETHOD_END
};
static driver_t afd_driver = {
"afd",
afd_methods,
0,
};
static devclass_t afd_devclass;
DRIVER_MODULE(afd, ata, afd_driver, afd_devclass, NULL, NULL);
MODULE_VERSION(afd, 1);
MODULE_DEPEND(afd, ata, 1, 1, 1);

View File

@ -1,86 +0,0 @@
/*-
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* 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.
*
* 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$
*/
/* ATAPI Rewriteable drive Capabilities and Mechanical Status Page */
struct afd_capabilities {
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_capacity {
u_int32_t capacity;
u_int32_t blocksize;
};
struct afd_capacity_big {
u_int64_t capacity;
u_int32_t blocksize;
};
struct afd_softc {
u_int64_t mediasize;
u_int32_t heads;
u_int32_t sectors;
u_int32_t sectorsize;
struct disk *disk; /* virtual drives */
};

View File

@ -1,739 +0,0 @@
/*-
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* 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.
*
* 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ata.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ata.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/conf.h>
#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/mtio.h>
#include <sys/devicestat.h>
#include <sys/sema.h>
#include <sys/taskqueue.h>
#include <vm/uma.h>
#include <machine/bus.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/atapi-tape.h>
#include <ata_if.h>
/* device structure */
static d_open_t ast_open;
static d_close_t ast_close;
static d_ioctl_t ast_ioctl;
static d_strategy_t ast_strategy;
static struct cdevsw ast_cdevsw = {
.d_version = D_VERSION,
.d_open = ast_open,
.d_close = ast_close,
.d_read = physread,
.d_write = physwrite,
.d_ioctl = ast_ioctl,
.d_strategy = ast_strategy,
.d_name = "ast",
.d_flags = D_TAPE | D_TRACKCLOSE,
};
/* prototypes */
static int ast_sense(device_t);
static void ast_describe(device_t);
static void ast_done(struct ata_request *);
static int ast_mode_sense(device_t, int, void *, int);
static int ast_mode_select(device_t, void *, int);
static int ast_write_filemark(device_t, u_int8_t);
static int ast_read_position(device_t, int, struct ast_readposition *);
static int ast_space(device_t, u_int8_t, int32_t);
static int ast_locate(device_t, int, u_int32_t);
static int ast_prevent_allow(device_t, int);
static int ast_load_unload(device_t, u_int8_t);
static int ast_rewind(device_t);
static int ast_erase(device_t);
static int ast_test_ready(device_t);
static int ast_wait_dsc(device_t, int);
/* internal vars */
static u_int64_t ast_total = 0;
static MALLOC_DEFINE(M_AST, "ast_driver", "ATAPI tape driver buffers");
static int
ast_probe(device_t dev)
{
struct ata_device *atadev = device_get_softc(dev);
if ((atadev->param.config & ATA_PROTO_ATAPI) &&
(atadev->param.config & ATA_ATAPI_TYPE_MASK) == ATA_ATAPI_TYPE_TAPE)
return 0;
else
return ENXIO;
}
static int
ast_attach(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
struct ast_softc *stp;
struct ast_readposition position;
struct cdev *device;
if (!(stp = malloc(sizeof(struct ast_softc), M_AST, M_NOWAIT | M_ZERO))) {
device_printf(dev, "out of memory\n");
return ENOMEM;
}
device_set_ivars(dev, stp);
ata_setmode(dev);
if (ast_sense(dev)) {
device_set_ivars(dev, NULL);
free(stp, M_AST);
return ENXIO;
}
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(dev, ATAPI_TAPE_TRANSFER_PAGE,
&transfer, sizeof(transfer));
bzero(&identify, sizeof(struct ast_identifypage));
ast_mode_sense(dev, ATAPI_TAPE_IDENTIFY_PAGE,
&identify, sizeof(identify));
strncpy(identify.ident, "FBSD", 4);
ast_mode_select(dev, &identify, sizeof(identify));
ast_read_position(dev, 0, &position);
}
stp->stats = devstat_new_entry("ast", device_get_unit(dev), DEV_BSIZE,
DEVSTAT_NO_ORDERED_TAGS,
DEVSTAT_TYPE_SEQUENTIAL | DEVSTAT_TYPE_IF_IDE,
DEVSTAT_PRIORITY_TAPE);
device = make_dev(&ast_cdevsw, 0, UID_ROOT, GID_OPERATOR, 0640,
"ast%d", device_get_unit(dev));
device->si_drv1 = dev;
device->si_iosize_max = ch->dma.max_iosize ? ch->dma.max_iosize : DFLTPHYS;
stp->dev1 = device;
device = make_dev(&ast_cdevsw, 1, UID_ROOT, GID_OPERATOR, 0640,
"nast%d", device_get_unit(dev));
device->si_drv1 = dev;
device->si_iosize_max = ch->dma.max_iosize;
stp->dev2 = device;
/* announce we are here and ready */
ast_describe(dev);
return 0;
}
static int
ast_detach(device_t dev)
{
struct ast_softc *stp = device_get_ivars(dev);
/* detroy devices from the system so we dont get any further requests */
destroy_dev(stp->dev1);
destroy_dev(stp->dev2);
/* fail requests on the queue and any thats "in flight" for this device */
ata_fail_requests(dev);
/* dont leave anything behind */
devstat_remove_entry(stp->stats);
device_set_ivars(dev, NULL);
free(stp, M_AST);
return 0;
}
static int
ast_shutdown(device_t dev)
{
struct ata_device *atadev = device_get_softc(dev);
if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
ata_controlcmd(dev, ATA_FLUSHCACHE, 0, 0, 0);
return 0;
}
static int
ast_reinit(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
/* if detach pending, return error */
if (!(ch->devices & (ATA_ATAPI_MASTER << atadev->unit)))
return 1;
ata_setmode(dev);
return 0;
}
static int
ast_open(struct cdev *cdev, int flags, int fmt, struct thread *td)
{
device_t dev = cdev->si_drv1;
struct ata_device *atadev = device_get_softc(dev);
struct ast_softc *stp = device_get_ivars(dev);
if (!stp)
return ENXIO;
if (!device_is_attached(dev))
return EBUSY;
ast_test_ready(dev);
if (stp->cap.lock)
ast_prevent_allow(dev, 1);
if (ast_sense(dev))
device_printf(dev, "sense media type failed\n");
atadev->flags &= ~ATA_D_MEDIA_CHANGED;
stp->flags &= ~(F_DATA_WRITTEN | F_FM_WRITTEN);
ast_total = 0;
return 0;
}
static int
ast_close(struct cdev *cdev, int flags, int fmt, struct thread *td)
{
device_t dev = cdev->si_drv1;
struct ast_softc *stp = device_get_ivars(dev);
/* flush buffers, some drives fail here, they should report ctl = 0 */
if (stp->cap.ctl && (stp->flags & F_DATA_WRITTEN))
ast_write_filemark(dev, 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(dev, ATAPI_WF_WRITE);
/* if unit is zero rewind on close */
if (dev2unit(cdev) == 0)
ast_rewind(dev);
if (stp->cap.lock && count_dev(cdev) == 1)
ast_prevent_allow(dev, 0);
stp->flags &= ~F_CTL_WARN;
#ifdef AST_DEBUG
device_printf(dev, "%ju total bytes transferred\n", (uintmax_t)ast_total);
#endif
return 0;
}
static int
ast_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int flag, struct thread *td)
{
device_t dev = cdev->si_drv1;
struct ast_softc *stp = device_get_ivars(dev);
int error = 0;
switch (cmd) {
case MTIOCGET:
{
struct mtget *g = (struct mtget *) 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 *)data;
switch ((int16_t) (mt->mt_op)) {
case MTWEOF:
for (i=0; i < mt->mt_count && !error; i++)
error = ast_write_filemark(dev, ATAPI_WF_WRITE);
break;
case MTFSF:
if (mt->mt_count)
error = ast_space(dev, ATAPI_SP_FM, mt->mt_count);
break;
case MTBSF:
if (mt->mt_count)
error = ast_space(dev, ATAPI_SP_FM, -(mt->mt_count));
break;
case MTREW:
error = ast_rewind(dev);
break;
case MTOFFL:
error = ast_load_unload(dev, ATAPI_SS_EJECT);
break;
case MTNOP:
error = ast_write_filemark(dev, 0);
break;
case MTERASE:
error = ast_erase(dev);
break;
case MTEOD:
error = ast_space(dev, ATAPI_SP_EOD, 0);
break;
case MTRETENS:
error = ast_load_unload(dev, ATAPI_SS_RETENSION|ATAPI_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(dev, 0, &position)))
break;
*(u_int32_t *)data = position.tape;
}
break;
case MTIOCRDHPOS:
{
struct ast_readposition position;
if ((error = ast_read_position(dev, 1, &position)))
break;
*(u_int32_t *)data = position.tape;
}
break;
case MTIOCSLOCATE:
error = ast_locate(dev, 0, *(u_int32_t *)data);
break;
case MTIOCHLOCATE:
error = ast_locate(dev, 1, *(u_int32_t *)data);
break;
default:
error = ata_device_ioctl(dev, cmd, data);
}
return error;
}
static void
ast_strategy(struct bio *bp)
{
device_t dev = bp->bio_dev->si_drv1;
struct ast_softc *stp = device_get_ivars(dev);
struct ata_request *request;
u_int32_t blkcount;
int8_t ccb[16];
/* if it's a null transfer, return immediatly. */
if (bp->bio_bcount == 0) {
bp->bio_resid = 0;
biodone(bp);
return;
}
if (!(bp->bio_cmd == BIO_READ) && stp->flags & F_WRITEPROTECT) {
biofinish(bp, NULL, EPERM);
return;
}
/* check for != blocksize requests */
if (bp->bio_bcount % stp->blksize) {
device_printf(dev, "transfers must be multiple of %d\n", stp->blksize);
biofinish(bp, NULL, EIO);
return;
}
/* warn about transfers bigger than the device suggests */
if (bp->bio_bcount > stp->blksize * stp->cap.ctl) {
if ((stp->flags & F_CTL_WARN) == 0) {
device_printf(dev, "WARNING: CTL exceeded %ld>%d\n",
bp->bio_bcount, stp->blksize * stp->cap.ctl);
stp->flags |= F_CTL_WARN;
}
}
bzero(ccb, sizeof(ccb));
if (bp->bio_cmd == BIO_READ)
ccb[0] = ATAPI_READ;
else
ccb[0] = ATAPI_WRITE;
blkcount = bp->bio_bcount / stp->blksize;
ccb[1] = 1;
ccb[2] = blkcount >> 16;
ccb[3] = blkcount >> 8;
ccb[4] = blkcount;
if (!(request = ata_alloc_request())) {
biofinish(bp, NULL, ENOMEM);
return;
}
request->dev = dev;
request->driver = bp;
bcopy(ccb, request->u.atapi.ccb, 16);
request->data = bp->bio_data;
request->bytecount = blkcount * stp->blksize;
request->transfersize = min(request->bytecount, 65534);
request->timeout = (ccb[0] == ATAPI_WRITE_BIG) ? 180 : 120;
request->retries = 2;
request->callback = ast_done;
switch (bp->bio_cmd) {
case BIO_READ:
request->flags |= (ATA_R_ATAPI | ATA_R_READ);
break;
case BIO_WRITE:
request->flags |= (ATA_R_ATAPI | ATA_R_WRITE);
break;
default:
device_printf(dev, "unknown BIO operation\n");
ata_free_request(request);
biofinish(bp, NULL, EIO);
return;
}
devstat_start_transaction_bio(stp->stats, bp);
ata_queue_request(request);
}
static void
ast_done(struct ata_request *request)
{
struct ast_softc *stp = device_get_ivars(request->dev);
struct bio *bp = request->driver;
/* finish up transfer */
if ((bp->bio_error = request->result))
bp->bio_flags |= BIO_ERROR;
if (bp->bio_cmd == BIO_WRITE)
stp->flags |= F_DATA_WRITTEN;
bp->bio_resid = bp->bio_bcount - request->donecount;
ast_total += (bp->bio_bcount - bp->bio_resid);
biofinish(bp, stp->stats, 0);
ata_free_request(request);
}
static int
ast_sense(device_t dev)
{
struct ast_softc *stp = device_get_ivars(dev);
int count;
/* get drive capabilities, some bugridden drives needs this repeated */
for (count = 0 ; count < 5 ; count++) {
if (!ast_mode_sense(dev, ATAPI_TAPE_CAP_PAGE,
&stp->cap, sizeof(stp->cap)) &&
stp->cap.page_code == ATAPI_TAPE_CAP_PAGE) {
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 int
ast_mode_sense(device_t dev, 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 = ata_atapicmd(dev, ccb, pagebuf, pagesize, ATA_R_READ, 10);
return error;
}
static int
ast_mode_select(device_t dev, 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 };
return ata_atapicmd(dev, ccb, pagebuf, pagesize, 0, 10);
}
static int
ast_write_filemark(device_t dev, u_int8_t function)
{
struct ast_softc *stp = device_get_ivars(dev);
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 = ata_atapicmd(dev, ccb, NULL, 0, 0, 10);
if (error)
return error;
return ast_wait_dsc(dev, 10*60);
}
static int
ast_read_position(device_t dev, 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 = ata_atapicmd(dev, ccb, (caddr_t)position,
sizeof(struct ast_readposition), ATA_R_READ, 10);
position->tape = ntohl(position->tape);
position->host = ntohl(position->host);
return error;
}
static int
ast_space(device_t dev, 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 ata_atapicmd(dev, ccb, NULL, 0, 0, 60*60);
}
static int
ast_locate(device_t dev, 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 = ata_atapicmd(dev, ccb, NULL, 0, 0, 10);
if (error)
return error;
return ast_wait_dsc(dev, 60*60);
}
static int
ast_prevent_allow(device_t dev, 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 ata_atapicmd(dev, ccb, NULL, 0, 0, 30);
}
static int
ast_load_unload(device_t dev, u_int8_t function)
{
struct ast_softc *stp = device_get_ivars(dev);
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 & ATAPI_SS_EJECT) && !stp->cap.eject)
return 0;
error = ata_atapicmd(dev, ccb, NULL, 0, 0, 10);
if (error)
return error;
pause("astlu", 1 * hz);
if (function == ATAPI_SS_EJECT)
return 0;
return ast_wait_dsc(dev, 60*60);
}
static int
ast_rewind(device_t dev)
{
int8_t ccb[16] = { ATAPI_REZERO, 0x01, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
int error;
error = ata_atapicmd(dev, ccb, NULL, 0, 0, 10);
if (error)
return error;
return ast_wait_dsc(dev, 60*60);
}
static int
ast_erase(device_t dev)
{
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(dev)))
return error;
return ata_atapicmd(dev, ccb, NULL, 0, 0, 60*60);
}
static int
ast_test_ready(device_t dev)
{
int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
return ata_atapicmd(dev, ccb, NULL, 0, 0, 30);
}
static int
ast_wait_dsc(device_t dev, 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 = ata_atapicmd(dev, ccb, NULL, 0, 0, 0);
if (error != EBUSY)
break;
pause("atpwt", hz / 2);
timeout -= (hz / 2);
}
return error;
}
static void
ast_describe(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
struct ast_softc *stp = device_get_ivars(dev);
if (bootverbose) {
device_printf(dev, "<%.40s/%.8s> tape drive at ata%d as %s\n",
atadev->param.model, atadev->param.revision,
device_get_unit(ch->dev), ata_unit2str(atadev));
device_printf(dev, "%dKB/s, ", stp->cap.max_speed);
printf("transfer limit %d blk%s, ",
stp->cap.ctl, (stp->cap.ctl > 1) ? "s" : "");
printf("%dKB buffer, ", (stp->cap.buffer_size * DEV_BSIZE) / 1024);
printf("%s %s\n", ata_mode2str(atadev->mode),
ata_satarev2str(ATA_GETREV(device_get_parent(dev), atadev->unit)));
device_printf(dev, "Medium: ");
switch (stp->cap.medium_type) {
case 0x00:
printf("none"); break;
case 0x17:
printf("Travan 1 (400 Mbyte)"); break;
case 0xb6:
printf("Travan 4 (4 Gbyte)"); break;
case 0xda:
printf("OnStream ADR (15Gyte)"); break;
default:
printf("unknown (0x%x)", stp->cap.medium_type);
}
if (stp->cap.readonly) printf(", readonly");
if (stp->cap.reverse) printf(", reverse");
if (stp->cap.eformat) printf(", eformat");
if (stp->cap.qfa) printf(", qfa");
if (stp->cap.lock) printf(", lock");
if (stp->cap.locked) printf(", locked");
if (stp->cap.prevent) printf(", prevent");
if (stp->cap.eject) printf(", eject");
if (stp->cap.disconnect) printf(", disconnect");
if (stp->cap.ecc) printf(", ecc");
if (stp->cap.compress) printf(", compress");
if (stp->cap.blk512) printf(", 512b");
if (stp->cap.blk1024) printf(", 1024b");
if (stp->cap.blk32k) printf(", 32kb");
printf("\n");
}
else {
device_printf(dev, "TAPE <%.40s/%.8s> at ata%d-%s %s %s\n",
atadev->param.model, atadev->param.revision,
device_get_unit(ch->dev), ata_unit2str(atadev),
ata_mode2str(atadev->mode),
ata_satarev2str(ATA_GETREV(device_get_parent(dev), atadev->unit)));
}
}
static device_method_t ast_methods[] = {
/* device interface */
DEVMETHOD(device_probe, ast_probe),
DEVMETHOD(device_attach, ast_attach),
DEVMETHOD(device_detach, ast_detach),
DEVMETHOD(device_shutdown, ast_shutdown),
/* ATA methods */
DEVMETHOD(ata_reinit, ast_reinit),
DEVMETHOD_END
};
static driver_t ast_driver = {
"ast",
ast_methods,
0,
};
static devclass_t ast_devclass;
DRIVER_MODULE(ast, ata, ast_driver, ast_devclass, NULL, NULL);
MODULE_VERSION(ast, 1);
MODULE_DEPEND(ast, ata, 1, 1, 1);

View File

@ -1,157 +0,0 @@
/*-
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* 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.
*
* 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$
*/
/* 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 {
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 atapi_params *param; /* drive parameters table */
struct ast_cappage cap; /* capabilities page info */
struct devstat *stats; /* devstat entry */
struct cdev *dev1, *dev2; /* device place holders */
};

View File

@ -51,25 +51,12 @@ __FBSDID("$FreeBSD$");
#include <dev/ata/ata-pci.h>
#include <ata_if.h>
#ifndef ATA_CAM
struct ata_serialize {
struct mtx locked_mtx;
int locked_ch;
int restart_ch;
};
#endif
/* local prototypes */
static int ata_acard_chipinit(device_t dev);
static int ata_acard_ch_attach(device_t dev);
static int ata_acard_status(device_t dev);
static int ata_acard_850_setmode(device_t dev, int target, int mode);
static int ata_acard_86X_setmode(device_t dev, int target, int mode);
#ifndef ATA_CAM
static int ata_acard_chipdeinit(device_t dev);
static int ata_serialize(device_t dev, int flags);
static void ata_serialize_init(struct ata_serialize *serial);
#endif
/* misc defines */
#define ATP_OLD 1
@ -97,9 +84,6 @@ ata_acard_probe(device_t dev)
ata_set_desc(dev);
ctlr->chipinit = ata_acard_chipinit;
#ifndef ATA_CAM
ctlr->chipdeinit = ata_acard_chipdeinit;
#endif
return (BUS_PROBE_DEFAULT);
}
@ -107,9 +91,6 @@ static int
ata_acard_chipinit(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
#ifndef ATA_CAM
struct ata_serialize *serial;
#endif
if (ata_setup_interrupt(dev, ata_generic_intr))
return ENXIO;
@ -118,40 +99,15 @@ ata_acard_chipinit(device_t dev)
ctlr->ch_detach = ata_pci_ch_detach;
if (ctlr->chip->cfg1 == ATP_OLD) {
ctlr->setmode = ata_acard_850_setmode;
#ifndef ATA_CAM
ctlr->locking = ata_serialize;
serial = malloc(sizeof(struct ata_serialize),
M_ATAPCI, M_WAITOK | M_ZERO);
ata_serialize_init(serial);
ctlr->chipset_data = serial;
#else
/* Work around the lack of channel serialization in ATA_CAM. */
ctlr->channels = 1;
device_printf(dev, "second channel ignored\n");
#endif
}
else
ctlr->setmode = ata_acard_86X_setmode;
return 0;
}
#ifndef ATA_CAM
static int
ata_acard_chipdeinit(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
struct ata_serialize *serial;
if (ctlr->chip->cfg1 == ATP_OLD) {
serial = ctlr->chipset_data;
mtx_destroy(&serial->locked_mtx);
free(serial, M_ATAPCI);
ctlr->chipset_data = NULL;
}
return (0);
}
#endif
static int
ata_acard_ch_attach(device_t dev)
{
@ -169,12 +125,8 @@ ata_acard_ch_attach(device_t dev)
static int
ata_acard_status(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
if (ctlr->chip->cfg1 == ATP_OLD &&
ATA_LOCKING(dev, ATA_LF_WHICH) != ch->unit)
return 0;
if (ch->dma.flags & ATA_DMA_ACTIVE) {
int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
@ -243,56 +195,4 @@ ata_acard_86X_setmode(device_t dev, int target, int mode)
return (mode);
}
#ifndef ATA_CAM
static void
ata_serialize_init(struct ata_serialize *serial)
{
mtx_init(&serial->locked_mtx, "ATA serialize lock", NULL, MTX_DEF);
serial->locked_ch = -1;
serial->restart_ch = -1;
}
static int
ata_serialize(device_t dev, int flags)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
struct ata_serialize *serial;
int res;
serial = ctlr->chipset_data;
mtx_lock(&serial->locked_mtx);
switch (flags) {
case ATA_LF_LOCK:
if (serial->locked_ch == -1)
serial->locked_ch = ch->unit;
if (serial->locked_ch != ch->unit)
serial->restart_ch = ch->unit;
break;
case ATA_LF_UNLOCK:
if (serial->locked_ch == ch->unit) {
serial->locked_ch = -1;
if (serial->restart_ch != -1) {
if ((ch = ctlr->interrupt[serial->restart_ch].argument)) {
serial->restart_ch = -1;
mtx_unlock(&serial->locked_mtx);
ata_start(dev);
return -1;
}
}
}
break;
case ATA_LF_WHICH:
break;
}
res = serial->locked_ch;
mtx_unlock(&serial->locked_mtx);
return res;
}
#endif
ATA_DECLARE_DRIVER(ata_acard);

View File

@ -213,10 +213,8 @@ ata_ali_ch_attach(device_t dev)
if (ch->dma.max_iosize > 256 * 512)
ch->dma.max_iosize = 256 * 512;
}
#ifdef ATA_CAM
if (ctlr->chip->cfg2 & ALI_NEW)
ch->flags |= ATA_NO_ATAPI_DMA;
#endif
return 0;
}

View File

@ -908,9 +908,6 @@ static void
ata_intel_31244_tf_write(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(request->parent);
#ifndef ATA_CAM
struct ata_device *atadev = device_get_softc(request->dev);
#endif
if (request->flags & ATA_R_48BIT) {
ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
@ -926,38 +923,12 @@ ata_intel_31244_tf_write(struct ata_request *request)
else {
ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count);
#ifndef ATA_CAM
if (atadev->flags & ATA_D_USE_CHS) {
int heads, sectors;
if (atadev->param.atavalid & ATA_FLAG_54_58) {
heads = atadev->param.current_heads;
sectors = atadev->param.current_sectors;
}
else {
heads = atadev->param.heads;
sectors = atadev->param.sectors;
}
ATA_IDX_OUTB(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1);
ATA_IDX_OUTB(ch, ATA_CYL_LSB,
(request->u.ata.lba / (sectors * heads)));
ATA_IDX_OUTB(ch, ATA_CYL_MSB,
(request->u.ata.lba / (sectors * heads)) >> 8);
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(request->unit) |
(((request->u.ata.lba% (sectors * heads)) /
sectors) & 0xf));
}
else {
#endif
ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba);
ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
ATA_IDX_OUTB(ch, ATA_DRIVE,
ATA_D_IBM | ATA_D_LBA | ATA_DEV(request->unit) |
((request->u.ata.lba >> 24) & 0x0f));
#ifndef ATA_CAM
}
#endif
}
}

View File

@ -119,9 +119,7 @@ ata_ite_ch_attach(device_t dev)
error = ata_pci_ch_attach(dev);
ch->flags |= ATA_CHECKS_CABLE;
#ifdef ATA_CAM
ch->flags |= ATA_NO_ATAPI_DMA;
#endif
return (error);
}

View File

@ -288,9 +288,6 @@ static void
ata_serverworks_tf_write(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(request->parent);
#ifndef ATA_CAM
struct ata_device *atadev = device_get_softc(request->dev);
#endif
if (request->flags & ATA_R_48BIT) {
ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
@ -306,38 +303,12 @@ ata_serverworks_tf_write(struct ata_request *request)
else {
ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);
#ifndef ATA_CAM
if (atadev->flags & ATA_D_USE_CHS) {
int heads, sectors;
if (atadev->param.atavalid & ATA_FLAG_54_58) {
heads = atadev->param.current_heads;
sectors = atadev->param.current_sectors;
}
else {
heads = atadev->param.heads;
sectors = atadev->param.sectors;
}
ATA_IDX_OUTW(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1);
ATA_IDX_OUTW(ch, ATA_CYL_LSB,
(request->u.ata.lba / (sectors * heads)));
ATA_IDX_OUTW(ch, ATA_CYL_MSB,
(request->u.ata.lba / (sectors * heads)) >> 8);
ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(request->unit) |
(((request->u.ata.lba% (sectors * heads)) /
sectors) & 0xf));
}
else {
#endif
ATA_IDX_OUTW(ch, ATA_SECTOR, request->u.ata.lba);
ATA_IDX_OUTW(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
ATA_IDX_OUTW(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
ATA_IDX_OUTW(ch, ATA_DRIVE,
ATA_D_IBM | ATA_D_LBA | ATA_DEV(request->unit) |
((request->u.ata.lba >> 24) & 0x0f));
#ifndef ATA_CAM
}
#endif
}
}

View File

@ -240,9 +240,7 @@ ata_cmd_ch_attach(device_t dev)
if (ctlr->chip->cfg2 & SII_INTR)
ch->hw.status = ata_cmd_status;
#ifdef ATA_CAM
ch->flags |= ATA_NO_ATAPI_DMA;
#endif
return 0;
}

View File

@ -104,7 +104,6 @@ device fdc
# ATA controllers
device ahci # AHCI-compatible SATA controllers
device ata # Legacy ATA/SATA controllers
options ATA_CAM # Handle legacy controllers with CAM
options ATA_STATIC_ID # Static device numbering
device mvs # Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA
device siis # SiliconImage SiI3124/SiI3132/SiI3531 SATA

View File

@ -51,7 +51,6 @@ device pci
# ATA and ATAPI devices
device ata
options ATA_CAM
options ATA_STATIC_ID # Static device numbering
# ATA/SCSI peripherals

View File

@ -86,7 +86,6 @@ device usb # USB Bus (required for USB)
# ATA controllers
device ahci # AHCI-compatible SATA controllers
device ata # Legacy ATA/SATA controllers
options ATA_CAM # Handle legacy controllers with CAM
device mvs # Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA
device siis # SiliconImage SiI3124/SiI3132/SiI3531 SATA

View File

@ -107,7 +107,6 @@ device pci
# ATA controllers
device ahci # AHCI-compatible SATA controllers
device ata # Legacy ATA/SATA controllers
options ATA_CAM # Handle legacy controllers with CAM
options ATA_STATIC_ID # Static device numbering
device mvs # Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA
device siis # SiliconImage SiI3124/SiI3132/SiI3531 SATA

View File

@ -106,7 +106,6 @@ options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required
device pci
#device ata
#device atadisk
device uart
# Pseudo
device loop

View File

@ -80,7 +80,6 @@ options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required
device pci
#device ata
#device atadisk
device uart
# Pseudo
device loop

View File

@ -79,7 +79,6 @@ options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required
device pci
#device ata
#device atadisk
#options XLR_PERFMON # Enable XLR processor activity monitoring
options BREAK_TO_DEBUGGER
device uart

View File

@ -57,5 +57,4 @@ device da
device pass
device ata
options ATA_CAM
options ATA_STATIC_ID # Static device numbering

View File

@ -81,7 +81,6 @@ device siis
device da
device scbus
#device ata
#device atadisk
# USB
device usb # USB Bus (required)

View File

@ -4,7 +4,6 @@ files "../malta/files.malta"
cpu CPU_MIPS4KC
device pci
device ata
options ATA_CAM
device scbus # SCSI bus (required for ATA/SCSI)
device cd # CD

View File

@ -8,6 +8,5 @@ SUBDIR += atacbus
SUBDIR += ataisa
.endif
SUBDIR += atapci
SUBDIR += atadisk atapicd atapifd atapist ataraid atapicam #atacam
.include <bsd.subdir.mk>

View File

@ -1,9 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/ata
KMOD= atacam
SRCS= ata-cam.c
SRCS+= opt_ata.h opt_cam.h ata_if.h device_if.h bus_if.h pci_if.h
.include <bsd.kmod.mk>

View File

@ -1,13 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/ata ${.CURDIR}/../../../${MACHINE}/${MACHINE}
KMOD= atadisk
SRCS= ata-disk.c ${ata_machdep}
SRCS+= opt_ata.h ata_if.h device_if.h bus_if.h pci_if.h
.if exists(${.CURDIR}/../../../${MACHINE}/${MACHINE}/ata_machdep.c)
ata_machdep= ata_machdep.c
.endif
.include <bsd.kmod.mk>

View File

@ -1,9 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/ata
KMOD= atapicam
SRCS= atapi-cam.c
SRCS+= opt_ata.h opt_cam.h ata_if.h device_if.h bus_if.h pci_if.h
.include <bsd.kmod.mk>

View File

@ -1,9 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/ata
KMOD= atapicd
SRCS= atapi-cd.c
SRCS+= opt_ata.h ata_if.h device_if.h bus_if.h pci_if.h
.include <bsd.kmod.mk>

View File

@ -1,9 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/ata
KMOD= atapifd
SRCS= atapi-fd.c
SRCS+= opt_ata.h ata_if.h device_if.h bus_if.h pci_if.h
.include <bsd.kmod.mk>

View File

@ -1,9 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/ata
KMOD= atapist
SRCS= atapi-tape.c
SRCS+= opt_ata.h ata_if.h device_if.h bus_if.h pci_if.h
.include <bsd.kmod.mk>

View File

@ -1,9 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/ata
KMOD= ataraid
SRCS= ata-raid.c
SRCS+= opt_ata.h ata_if.h device_if.h bus_if.h pci_if.h
.include <bsd.kmod.mk>

View File

@ -83,7 +83,6 @@ device fdc
# ATA controllers
device ahci # AHCI-compatible SATA controllers
device ata # Legacy ATA/SATA controllers
options ATA_CAM # Handle legacy controllers with CAM
options ATA_STATIC_ID # Static device numbering
device mvs # Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA
device siis # SiliconImage SiI3124/SiI3132/SiI3531 SATA

View File

@ -612,7 +612,6 @@ nodevice ida # Compaq Smart RAID
nodevice mlx # Mylex DAC960
nodevice amr # AMI MegaRAID
nodevice twe # 3ware ATA RAID
nodevice ataraid
nodevice cm
nodevice ex
nodevice fea

View File

@ -100,7 +100,6 @@ device agp
# ATA controllers
device ahci # AHCI-compatible SATA controllers
device ata # Legacy ATA/SATA controllers
options ATA_CAM # Handle legacy controllers with CAM
device mvs # Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA
device siis # SiliconImage SiI3124/SiI3132/SiI3531 SATA

View File

@ -95,7 +95,6 @@ device agp
# ATA controllers
device ahci # AHCI-compatible SATA controllers
device ata # Legacy ATA/SATA controllers
options ATA_CAM # Handle legacy controllers with CAM
device mvs # Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA
device siis # SiliconImage SiI3124/SiI3132/SiI3531 SATA

View File

@ -57,7 +57,6 @@ options WITNESS
options WITNESS_SKIPSPIN
device ata
options ATA_CAM
device bpf
device cfi
device crypto

View File

@ -97,7 +97,6 @@ device fhc
# ATA controllers
device ahci # AHCI-compatible SATA controllers
device ata # Legacy ATA/SATA controllers
options ATA_CAM # Handle legacy controllers with CAM
device mvs # Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA
device siis # SiliconImage SiI3124/SiI3132/SiI3531 SATA