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:
parent
3b0b7ffbb9
commit
45f6d66569
@ -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 \
|
||||
|
@ -6,7 +6,6 @@
|
||||
# XXX MISSING: icheck ncheck
|
||||
|
||||
SUBDIR=adjkerntz \
|
||||
atacontrol \
|
||||
badsect \
|
||||
camcontrol \
|
||||
ccdconfig \
|
||||
|
@ -1,6 +0,0 @@
|
||||
#$FreeBSD$
|
||||
|
||||
PROG= atacontrol
|
||||
MAN= atacontrol.8
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -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.
|
@ -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, ¶ms) < 0)
|
||||
err(1, "ioctl(IOCATAGPARM)");
|
||||
cap_print(¶ms);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
@ -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 \
|
||||
|
@ -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 :
|
||||
|
@ -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.
|
@ -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.
|
@ -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
|
||||
|
@ -76,7 +76,6 @@ device md
|
||||
|
||||
# SATA
|
||||
#device ata
|
||||
#device atadisk
|
||||
#device mvs
|
||||
|
||||
# Serial ports
|
||||
|
@ -76,7 +76,6 @@ device da
|
||||
|
||||
# SATA
|
||||
device ata
|
||||
device atadisk
|
||||
#device mvs
|
||||
|
||||
# Serial ports
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -70,7 +70,6 @@ device da
|
||||
|
||||
# SATA
|
||||
device ata
|
||||
options ATA_CAM
|
||||
|
||||
# Flattened Device Tree
|
||||
options FDT
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
@ -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 */
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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);
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
@ -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;
|
@ -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))
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
@ -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 */
|
||||
};
|
@ -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);
|
||||
|
@ -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 */
|
||||
};
|
||||
|
@ -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);
|
@ -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 */
|
||||
};
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -57,5 +57,4 @@ device da
|
||||
device pass
|
||||
|
||||
device ata
|
||||
options ATA_CAM
|
||||
options ATA_STATIC_ID # Static device numbering
|
||||
|
@ -81,7 +81,6 @@ device siis
|
||||
device da
|
||||
device scbus
|
||||
#device ata
|
||||
#device atadisk
|
||||
|
||||
# USB
|
||||
device usb # USB Bus (required)
|
||||
|
@ -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
|
||||
|
@ -8,6 +8,5 @@ SUBDIR += atacbus
|
||||
SUBDIR += ataisa
|
||||
.endif
|
||||
SUBDIR += atapci
|
||||
SUBDIR += atadisk atapicd atapifd atapist ataraid atapicam #atacam
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -57,7 +57,6 @@ options WITNESS
|
||||
options WITNESS_SKIPSPIN
|
||||
|
||||
device ata
|
||||
options ATA_CAM
|
||||
device bpf
|
||||
device cfi
|
||||
device crypto
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user