Add experimental support for SATA Port Multipliers

Support is working on the Silicon Image SiI3124/3132.
Support is working on some AHCI chips but far from all.

Remember this is WIP, so test reports and (constructive) suggestions are welcome!
This commit is contained in:
Søren Schmidt 2008-04-10 13:05:05 +00:00
parent 3cba562fb9
commit 9f82379c24
24 changed files with 1297 additions and 649 deletions

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -62,7 +62,6 @@ static struct cdevsw ata_cdevsw = {
/* prototypes */
static void ata_boot_attach(void);
static device_t ata_add_child(device_t, struct ata_device *, int);
static int ata_getparam(struct ata_device *, int);
static void bswap(int8_t *, int);
static void btrim(int8_t *, int);
static void bpack(int8_t *, int8_t *, int);
@ -75,6 +74,7 @@ devclass_t ata_devclass;
uma_zone_t ata_request_zone;
uma_zone_t ata_composite_zone;
int ata_wc = 1;
int ata_setmax = 0;
/* local vars */
static int ata_dma = 1;
@ -91,6 +91,9 @@ SYSCTL_INT(_hw_ata, OID_AUTO, atapi_dma, CTLFLAG_RDTUN, &atapi_dma, 0,
TUNABLE_INT("hw.ata.wc", &ata_wc);
SYSCTL_INT(_hw_ata, OID_AUTO, wc, CTLFLAG_RDTUN, &ata_wc, 0,
"ATA disk write caching");
TUNABLE_INT("hw.ata.setmax", &ata_setmax);
SYSCTL_INT(_hw_ata, OID_AUTO, setmax, CTLFLAG_RDTUN, &ata_setmax, 0,
"ATA disk set max native address");
/*
* newbus device interface related functions
@ -404,13 +407,13 @@ ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
if (children[i] && device_is_attached(children[i])) {
struct ata_device *atadev = device_get_softc(children[i]);
if (atadev->unit == ATA_MASTER) {
if (atadev->unit == ATA_MASTER) { /* XXX SOS PM */
strncpy(devices->name[0],
device_get_nameunit(children[i]), 32);
bcopy(&atadev->param, &devices->params[0],
sizeof(struct ata_params));
}
if (atadev->unit == ATA_SLAVE) {
if (atadev->unit == ATA_SLAVE) { /* XXX SOS PM */
strncpy(devices->name[1],
device_get_nameunit(children[i]), 32);
bcopy(&atadev->param, &devices->params[1],
@ -569,7 +572,7 @@ ata_add_child(device_t parent, struct ata_device *atadev, int unit)
return child;
}
static int
int
ata_getparam(struct ata_device *atadev, int init)
{
struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
@ -577,11 +580,9 @@ ata_getparam(struct ata_device *atadev, int init)
u_int8_t command = 0;
int error = ENOMEM, retries = 2;
if (ch->devices &
(atadev->unit == ATA_MASTER ? ATA_ATA_MASTER : ATA_ATA_SLAVE))
if (ch->devices & (ATA_ATA_MASTER << atadev->unit))
command = ATA_ATA_IDENTIFY;
if (ch->devices &
(atadev->unit == ATA_MASTER ? ATA_ATAPI_MASTER : ATA_ATAPI_SLAVE))
if (ch->devices & (ATA_ATAPI_MASTER << atadev->unit))
command = ATA_ATAPI_IDENTIFY;
if (!command)
return ENXIO;
@ -631,7 +632,7 @@ ata_getparam(struct ata_device *atadev, int init)
if (bootverbose)
printf("ata%d-%s: pio=%s wdma=%s udma=%s cable=%s wire\n",
device_get_unit(ch->dev),
atadev->unit == ATA_MASTER ? "master" : "slave",
ata_unit2str(atadev),
ata_mode2str(ata_pmode(atacap)),
ata_mode2str(ata_wmode(atacap)),
ata_mode2str(ata_umode(atacap)),
@ -643,13 +644,13 @@ ata_getparam(struct ata_device *atadev, int init)
if ((atadev->param.config & ATA_PROTO_ATAPI) &&
(atadev->param.config != ATA_CFA_MAGIC1) &&
(atadev->param.config != ATA_CFA_MAGIC2)) {
if (atapi_dma && ch->dma &&
if (atapi_dma &&
(atadev->param.config & ATA_DRQ_MASK) != ATA_DRQ_INTR &&
ata_umode(&atadev->param) >= ATA_UDMA2)
atadev->mode = ATA_DMA_MAX;
}
else {
if (ata_dma && ch->dma &&
if (ata_dma &&
(ata_umode(&atadev->param) > 0 ||
ata_wmode(&atadev->param) > 0))
atadev->mode = ATA_DMA_MAX;
@ -667,52 +668,39 @@ int
ata_identify(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
struct ata_device *master = NULL, *slave = NULL;
device_t master_child = NULL, slave_child = NULL;
int master_unit = -1, slave_unit = -1;
struct ata_device *devices[ATA_PM];
device_t childdevs[ATA_PM];
int i, unit = -1;
if (ch->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER)) {
if (!(master = malloc(sizeof(struct ata_device),
M_ATA, M_NOWAIT | M_ZERO))) {
device_printf(dev, "out of memory\n");
return ENOMEM;
}
master->unit = ATA_MASTER;
}
if (ch->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE)) {
if (!(slave = malloc(sizeof(struct ata_device),
M_ATA, M_NOWAIT | M_ZERO))) {
free(master, M_ATA);
device_printf(dev, "out of memory\n");
return ENOMEM;
}
slave->unit = ATA_SLAVE;
}
if (bootverbose)
device_printf(dev, "identify ch->devices=%08x\n", ch->devices);
for (i = 0; i < ATA_PM; ++i) {
if (ch->devices & (((ATA_ATA_MASTER | ATA_ATAPI_MASTER) << i))) {
if (!(devices[i] = malloc(sizeof(struct ata_device),
M_ATA, M_NOWAIT | M_ZERO))) {
device_printf(dev, "out of memory\n");
return ENOMEM;
}
devices[i]->unit = i;
#ifdef ATA_STATIC_ID
if (ch->devices & ATA_ATA_MASTER)
master_unit = (device_get_unit(dev) << 1);
unit = (device_get_unit(dev) << 1) + i;
#endif
if (master && !(master_child = ata_add_child(dev, master, master_unit))) {
free(master, M_ATA);
master = NULL;
}
#ifdef ATA_STATIC_ID
if (ch->devices & ATA_ATA_SLAVE)
slave_unit = (device_get_unit(dev) << 1) + 1;
#endif
if (slave && !(slave_child = ata_add_child(dev, slave, slave_unit))) {
free(slave, M_ATA);
slave = NULL;
}
if (slave && ata_getparam(slave, 1)) {
device_delete_child(dev, slave_child);
free(slave, M_ATA);
}
if (master && ata_getparam(master, 1)) {
device_delete_child(dev, master_child);
free(master, M_ATA);
if (!(childdevs[i] = ata_add_child(dev, devices[i], unit))) {
free(devices[i], M_ATA);
devices[i]=NULL;
}
else {
if (ata_getparam(devices[i], 1)) {
device_delete_child(dev, childdevs[i]);
free(devices[i], M_ATA);
childdevs[i] = NULL;
devices[i] = NULL;
}
}
}
devices[i] = NULL;
childdevs[i] = NULL;
}
bus_generic_probe(dev);
@ -810,8 +798,23 @@ ata_modify_if_48bit(struct ata_request *request)
case ATA_FLUSHCACHE:
request->u.ata.command = ATA_FLUSHCACHE48;
break;
case ATA_READ_NATIVE_MAX_ADDDRESS:
request->u.ata.command = ATA_READ_NATIVE_MAX_ADDDRESS48;
case ATA_SET_MAX_ADDRESS:
request->u.ata.command = ATA_SET_MAX_ADDRESS48;
break;
default:
return;
}
atadev->flags |= ATA_D_48BIT_ACTIVE;
}
else if (atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48) {
/* translate command into 48bit version */
switch (request->u.ata.command) {
case ATA_FLUSHCACHE:
request->u.ata.command = ATA_FLUSHCACHE48;
break;
case ATA_READ_NATIVE_MAX_ADDRESS:
request->u.ata.command = ATA_READ_NATIVE_MAX_ADDRESS48;
break;
case ATA_SET_MAX_ADDRESS:
request->u.ata.command = ATA_SET_MAX_ADDRESS48;
@ -833,6 +836,19 @@ ata_udelay(int interval)
pause("ataslp", interval/(1000000/hz));
}
char *
ata_unit2str(struct ata_device *atadev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
static char str[8];
if (ch->devices & ATA_PORTMULTIPLIER)
sprintf(str, "port%d", atadev->unit);
else
sprintf(str, "%s", atadev->unit == ATA_MASTER ? "master" : "slave");
return str;
}
char *
ata_mode2str(int mode)
{

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -149,6 +149,7 @@
/* SATA AHCI v1.0 register defines */
#define ATA_AHCI_CAP 0x00
#define ATA_AHCI_NPMASK 0x1f
#define ATA_AHCI_CAP_SPM 0x00020000
#define ATA_AHCI_CAP_CLO 0x01000000
#define ATA_AHCI_CAP_64BIT 0x80000000
@ -220,11 +221,13 @@
#define ATA_AHCI_P_SERR 0x130
#define ATA_AHCI_P_SACT 0x134
#define ATA_AHCI_P_CI 0x138
#define ATA_AHCI_P_SNTF 0x13C
#define ATA_AHCI_P_FBS 0x140
#define ATA_AHCI_CL_SIZE 32
#define ATA_AHCI_CL_OFFSET 0
#define ATA_AHCI_FB_OFFSET 1024
#define ATA_AHCI_CT_OFFSET 1024+256
#define ATA_AHCI_CT_OFFSET 1024+4096
#define ATA_AHCI_CT_SG_OFFSET 128
#define ATA_AHCI_CT_SIZE 256
@ -245,6 +248,13 @@ struct ata_ahci_cmd_tab {
struct ata_ahci_cmd_list {
u_int16_t cmd_flags;
#define ATA_AHCI_CMD_ATAPI 0x0020
#define ATA_AHCI_CMD_WRITE 0x0040
#define ATA_AHCI_CMD_PREFETCH 0x0080
#define ATA_AHCI_CMD_RESET 0x0100
#define ATA_AHCI_CMD_BIST 0x0200
#define ATA_AHCI_CMD_CLR_BUSY 0x0400
u_int16_t prd_length; /* PRD entries */
u_int32_t bytecount;
u_int64_t cmd_table_phys; /* 128byte aligned */
@ -291,7 +301,7 @@ struct ata_ahci_cmd_list {
#define ATA_PC98_CTLADDR_RID 8
#define ATA_PC98_BANKADDR_RID 9
#define ATA_IRQ_RID 0
#define ATA_DEV(device) ((device == ATA_MASTER) ? 0 : 1)
#define ATA_DEV(unit) ((unit == ATA_ATA_SLAVE) ? 0x10 : 0)
#define ATA_CFA_MAGIC1 0x844A
#define ATA_CFA_MAGIC2 0x848A
#define ATA_CFA_MAGIC3 0x8400
@ -343,6 +353,7 @@ struct ata_request {
u_int32_t bytecount; /* bytes to transfer */
u_int32_t transfersize; /* bytes pr transfer */
caddr_t data; /* pointer to data buf */
u_int32_t tag; /* HW tag of this request */
int flags;
#define ATA_R_CONTROL 0x00000001
#define ATA_R_READ 0x00000002
@ -364,7 +375,16 @@ struct ata_request {
u_int8_t status; /* ATA status */
u_int8_t error; /* ATA error */
u_int8_t dmastat; /* DMA status */
struct {
u_int8_t status; /* DMA status */
bus_dma_tag_t sg_tag; /* SG list DMA tag */
bus_dmamap_t sg_map; /* SG list DMA map */
void *sg; /* DMA transfer table */
bus_addr_t sg_bus; /* bus address of dmatab */
bus_dma_tag_t data_tag; /* data DMA tag */
bus_dmamap_t data_map; /* data DMA map */
u_int32_t cur_iosize; /* DMA data current IO size */
} dma;
u_int32_t donecount; /* bytes transferred */
int result; /* result error code */
void (*callback)(struct ata_request *request);
@ -398,6 +418,7 @@ struct ata_device {
device_t dev; /* device handle */
int unit; /* physical unit */
#define ATA_MASTER 0x00
#define ATA_PM 0x0f
#define ATA_SLAVE 0x10
struct ata_params param; /* ata param structure */
@ -429,40 +450,33 @@ struct ata_dmasetprd_args {
/* structure holding DMA related information */
struct ata_dma {
bus_dma_tag_t dmatag; /* parent DMA tag */
bus_dma_tag_t sg_tag; /* SG list DMA tag */
bus_dmamap_t sg_map; /* SG list DMA map */
void *sg; /* DMA transfer table */
bus_addr_t sg_bus; /* bus address of dmatab */
bus_dma_tag_t data_tag; /* data DMA tag */
bus_dmamap_t data_map; /* data DMA map */
bus_dma_tag_t work_tag; /* workspace DMA tag */
bus_dmamap_t work_map; /* workspace DMA map */
u_int8_t *work; /* workspace */
bus_addr_t work_bus; /* bus address of dmatab */
u_int32_t alignment; /* DMA SG list alignment */
u_int32_t boundary; /* DMA SG list boundary */
u_int32_t segsize; /* DMA SG list segment size */
u_int32_t max_iosize; /* DMA data max IO size */
u_int32_t cur_iosize; /* DMA data current IO size */
u_int64_t max_address; /* highest DMA'able address */
int flags;
#define ATA_DMA_READ 0x01 /* transaction is a read */
#define ATA_DMA_LOADED 0x02 /* DMA tables etc loaded */
#define ATA_DMA_ACTIVE 0x04 /* DMA transfer in progress */
#define ATA_DMA_ACTIVE 0x01 /* DMA transfer in progress */
void (*alloc)(device_t dev);
void (*free)(device_t dev);
void (*setprd)(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
int (*load)(device_t dev, caddr_t data, int32_t count, int dir, void *addr, int *nsegs);
int (*unload)(device_t dev);
int (*start)(device_t dev);
int (*stop)(device_t dev);
int (*load)(struct ata_request *request, void *addr, int *nsegs);
int (*unload)(struct ata_request *request);
int (*start)(struct ata_request *request);
int (*stop)(struct ata_request *request);
void (*reset)(device_t dev);
};
/* structure holding lowlevel functions */
struct ata_lowlevel {
u_int32_t (*softreset)(device_t dev, int pmport);
int (*pm_read)(device_t dev, int port, int reg, u_int32_t *result);
int (*pm_write)(device_t dev, int port, int reg, u_int32_t value);
int (*status)(device_t dev);
int (*begin_transaction)(struct ata_request *request);
int (*end_transaction)(struct ata_request *request);
@ -485,7 +499,7 @@ struct ata_channel {
struct resource *r_irq; /* interrupt of this channel */
void *ih; /* interrupt handle */
struct ata_lowlevel hw; /* lowlevel HW functions */
struct ata_dma *dma; /* DMA data / functions */
struct ata_dma dma; /* DMA data / functions */
int flags; /* channel flags */
#define ATA_NO_SLAVE 0x01
#define ATA_USE_16BIT 0x02
@ -494,11 +508,11 @@ struct ata_channel {
#define ATA_ALWAYS_DMASTAT 0x10
int devices; /* what is present */
#define ATA_ATA_MASTER 0x01
#define ATA_ATA_SLAVE 0x02
#define ATA_ATAPI_MASTER 0x04
#define ATA_ATAPI_SLAVE 0x08
#define ATA_PORTMULTIPLIER 0x10
#define ATA_ATA_MASTER 0x00000001
#define ATA_ATA_SLAVE 0x00000002
#define ATA_PORTMULTIPLIER 0x00008000
#define ATA_ATAPI_MASTER 0x00010000
#define ATA_ATAPI_SLAVE 0x00020000
struct mtx state_mtx; /* state lock */
int state; /* ATA channel state */
@ -524,6 +538,7 @@ extern int (*ata_raid_ioctl_func)(u_long cmd, caddr_t data);
extern struct intr_config_hook *ata_delayed_attach;
extern devclass_t ata_devclass;
extern int ata_wc;
extern int ata_setmax;
/* public prototypes */
/* ata-all.c: */
@ -535,10 +550,12 @@ int ata_suspend(device_t dev);
int ata_resume(device_t dev);
int ata_interrupt(void *data);
int ata_device_ioctl(device_t dev, u_long cmd, caddr_t data);
int ata_getparam(struct ata_device *atadev, int init);
int ata_identify(device_t dev);
void ata_default_registers(device_t dev);
void ata_modify_if_48bit(struct ata_request *request);
void ata_udelay(int interval);
char *ata_unit2str(struct ata_device *atadev);
char *ata_mode2str(int mode);
int ata_pmode(struct ata_params *ap);
int ata_wmode(struct ata_params *ap);

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2002 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 2002 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/disk.h>
#include <sys/cons.h>
#include <sys/sysctl.h>
#include <sys/sema.h>
#include <sys/taskqueue.h>
#include <vm/uma.h>
@ -54,10 +53,12 @@ __FBSDID("$FreeBSD$");
#include <ata_if.h>
/* prototypes */
static void ad_init(device_t);
static void ad_done(struct ata_request *);
static void ad_init(device_t dev);
static void 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);
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;
@ -93,8 +94,6 @@ 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;
u_int32_t lbasize;
u_int64_t lbasize48;
/* check that we have a virgin disk to attach */
if (device_get_ivars(dev))
@ -106,37 +105,12 @@ ad_attach(device_t dev)
}
device_set_ivars(dev, adp);
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);
/* get device geometry into internal structs */
ad_get_geometry(dev);
/* 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;
/* set the max size if configured */
if (ata_setmax)
ad_set_geometry(dev);
/* init device parameters */
ad_init(dev);
@ -151,10 +125,7 @@ ad_attach(device_t dev)
adp->disk->d_dump = ad_dump;
adp->disk->d_name = "ad";
adp->disk->d_drv1 = dev;
if (ch->dma)
adp->disk->d_maxsize = ch->dma->max_iosize;
else
adp->disk->d_maxsize = DFLTPHYS;
adp->disk->d_maxsize = ch->dma.max_iosize;
adp->disk->d_sectorsize = DEV_BSIZE;
adp->disk->d_mediasize = DEV_BSIZE * (off_t)adp->total_secs;
adp->disk->d_fwsectors = adp->sectors;
@ -249,7 +220,7 @@ ad_spindown(void *priv)
struct ata_device *atadev = device_get_softc(dev);
struct ata_request *request;
if(atadev->spindown == 0)
if (!atadev->spindown)
return;
device_printf(dev, "Idle, spin down\n");
atadev->spindown_state = 1;
@ -274,9 +245,9 @@ ad_strategy(struct bio *bp)
struct ata_device *atadev = device_get_softc(dev);
struct ata_request *request;
if (atadev->spindown != 0)
if (atadev->spindown)
callout_reset(&atadev->spindown_timer, hz * atadev->spindown,
ad_spindown, dev);
ad_spindown, dev);
if (!(request = ata_alloc_request())) {
device_printf(dev, "FAILURE - out of memory in start\n");
@ -292,7 +263,8 @@ ad_strategy(struct bio *bp)
device_printf(dev, "request while spun down, starting.\n");
atadev->spindown_state = 0;
request->timeout = 31;
} else {
}
else {
request->timeout = 5;
}
request->retries = 2;
@ -426,7 +398,105 @@ ad_init(device_t dev)
atadev->max_iosize = DEV_BSIZE;
}
void
static void
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);
/* 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;
}
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 = 5;
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 = 5;
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));
@ -458,8 +528,7 @@ ad_describe(device_t dev)
device_printf(dev, "%juMB <%s%s %.8s> at ata%d-%s %s%s\n",
adp->total_secs / (1048576 / DEV_BSIZE),
vendor, product, atadev->param.revision,
device_get_unit(ch->dev),
(atadev->unit == ATA_MASTER) ? "master" : "slave",
device_get_unit(ch->dev), ata_unit2str(atadev),
(adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "",
ata_mode2str(atadev->mode));
if (bootverbose) {

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -45,11 +45,11 @@ __FBSDID("$FreeBSD$");
#include <dev/ata/ata-pci.h>
/* prototypes */
static void ata_dmaalloc(device_t);
static void ata_dmafree(device_t);
static void ata_dmasetprd(void *, bus_dma_segment_t *, int, int);
static int ata_dmaload(device_t, caddr_t, int32_t, int, void *, int *);
static int ata_dmaunload(device_t);
static void ata_dmaalloc(device_t dev);
static void ata_dmafree(device_t dev);
static void ata_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
static int ata_dmaload(struct ata_request *request, void *addr, int *nsegs);
static int ata_dmaunload(struct ata_request *request);
/* local vars */
static MALLOC_DEFINE(M_ATADMA, "ata_dma", "ATA driver DMA");
@ -68,93 +68,63 @@ ata_dmainit(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
if ((ch->dma = malloc(sizeof(struct ata_dma), M_ATADMA, M_NOWAIT|M_ZERO))) {
ch->dma->alloc = ata_dmaalloc;
ch->dma->free = ata_dmafree;
ch->dma->setprd = ata_dmasetprd;
ch->dma->load = ata_dmaload;
ch->dma->unload = ata_dmaunload;
ch->dma->alignment = 2;
ch->dma->boundary = 65536;
ch->dma->segsize = 128 * DEV_BSIZE;
ch->dma->max_iosize = 128 * DEV_BSIZE;
ch->dma->max_address = BUS_SPACE_MAXADDR_32BIT;
}
ch->dma.alloc = ata_dmaalloc;
ch->dma.free = ata_dmafree;
ch->dma.setprd = ata_dmasetprd;
ch->dma.load = ata_dmaload;
ch->dma.unload = ata_dmaunload;
ch->dma.alignment = 2;
ch->dma.boundary = 65536;
ch->dma.segsize = 63536;
ch->dma.max_iosize = 128 * DEV_BSIZE;
ch->dma.max_address = BUS_SPACE_MAXADDR_32BIT;
}
static void
ata_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
{
struct ata_dc_cb_args *cba = (struct ata_dc_cb_args *)xsc;
struct ata_dc_cb_args *dcba = (struct ata_dc_cb_args *)xsc;
if (!(cba->error = error))
cba->maddr = segs[0].ds_addr;
if (!(dcba->error = error))
dcba->maddr = segs[0].ds_addr;
}
static void
ata_dmaalloc(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
struct ata_dc_cb_args ccba;
struct ata_dc_cb_args dcba;
if (bus_dma_tag_create(bus_get_dma_tag(dev), ch->dma->alignment, 0,
ch->dma->max_address, BUS_SPACE_MAXADDR,
NULL, NULL, ch->dma->max_iosize,
ATA_DMA_ENTRIES, ch->dma->segsize,
0, NULL, NULL, &ch->dma->dmatag))
if (bus_dma_tag_create(bus_get_dma_tag(dev), ch->dma.alignment, 0,
ch->dma.max_address, BUS_SPACE_MAXADDR,
NULL, NULL, ch->dma.max_iosize,
ATA_DMA_ENTRIES, ch->dma.segsize,
0, NULL, NULL, &ch->dma.dmatag))
goto error;
if (bus_dma_tag_create(ch->dma->dmatag, PAGE_SIZE, PAGE_SIZE,
ch->dma->max_address, BUS_SPACE_MAXADDR,
NULL, NULL, MAXTABSZ, 1, MAXTABSZ,
0, NULL, NULL, &ch->dma->sg_tag))
goto error;
if (bus_dma_tag_create(ch->dma->dmatag,ch->dma->alignment,ch->dma->boundary,
ch->dma->max_address, BUS_SPACE_MAXADDR,
NULL, NULL, ch->dma->max_iosize,
ATA_DMA_ENTRIES, ch->dma->segsize,
0, NULL, NULL, &ch->dma->data_tag))
goto error;
if (bus_dmamem_alloc(ch->dma->sg_tag, (void **)&ch->dma->sg, 0,
&ch->dma->sg_map))
goto error;
if (bus_dmamap_load(ch->dma->sg_tag, ch->dma->sg_map, ch->dma->sg,
MAXTABSZ, ata_dmasetupc_cb, &ccba, 0) || ccba.error) {
bus_dmamem_free(ch->dma->sg_tag, ch->dma->sg, ch->dma->sg_map);
goto error;
}
ch->dma->sg_bus = ccba.maddr;
if (bus_dmamap_create(ch->dma->data_tag, 0, &ch->dma->data_map))
goto error;
if (bus_dma_tag_create(ch->dma->dmatag, PAGE_SIZE, 64 * 1024,
ch->dma->max_address, BUS_SPACE_MAXADDR,
if (bus_dma_tag_create(ch->dma.dmatag, PAGE_SIZE, 64 * 1024,
ch->dma.max_address, BUS_SPACE_MAXADDR,
NULL, NULL, MAXWSPCSZ, 1, MAXWSPCSZ,
0, NULL, NULL, &ch->dma->work_tag))
0, NULL, NULL, &ch->dma.work_tag))
goto error;
if (bus_dmamem_alloc(ch->dma->work_tag, (void **)&ch->dma->work, 0,
&ch->dma->work_map))
if (bus_dmamem_alloc(ch->dma.work_tag, (void **)&ch->dma.work, 0,
&ch->dma.work_map))
goto error;
if (bus_dmamap_load(ch->dma->work_tag, ch->dma->work_map,ch->dma->work,
MAXWSPCSZ, ata_dmasetupc_cb, &ccba, 0) || ccba.error) {
bus_dmamem_free(ch->dma->work_tag,ch->dma->work, ch->dma->work_map);
if (bus_dmamap_load(ch->dma.work_tag, ch->dma.work_map ,ch->dma.work,
MAXWSPCSZ, ata_dmasetupc_cb, &dcba, BUS_DMA_NOWAIT) ||
dcba.error) {
bus_dmamem_free(ch->dma.work_tag, ch->dma.work, ch->dma.work_map);
goto error;
}
ch->dma->work_bus = ccba.maddr;
ch->dma.work_bus = dcba.maddr;
return;
error:
device_printf(dev, "WARNING - DMA allocation failed, disabling DMA\n");
ata_dmafree(dev);
free(ch->dma, M_ATADMA);
ch->dma = NULL;
}
static void
@ -162,39 +132,20 @@ ata_dmafree(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
if (ch->dma->work_bus) {
bus_dmamap_unload(ch->dma->work_tag, ch->dma->work_map);
bus_dmamem_free(ch->dma->work_tag, ch->dma->work, ch->dma->work_map);
ch->dma->work_bus = 0;
ch->dma->work_map = NULL;
ch->dma->work = NULL;
if (ch->dma.work_bus) {
bus_dmamap_unload(ch->dma.work_tag, ch->dma.work_map);
bus_dmamem_free(ch->dma.work_tag, ch->dma.work, ch->dma.work_map);
ch->dma.work_bus = 0;
ch->dma.work_map = NULL;
ch->dma.work = NULL;
}
if (ch->dma->work_tag) {
bus_dma_tag_destroy(ch->dma->work_tag);
ch->dma->work_tag = NULL;
if (ch->dma.work_tag) {
bus_dma_tag_destroy(ch->dma.work_tag);
ch->dma.work_tag = NULL;
}
if (ch->dma->sg_bus) {
bus_dmamap_unload(ch->dma->sg_tag, ch->dma->sg_map);
bus_dmamem_free(ch->dma->sg_tag, ch->dma->sg, ch->dma->sg_map);
ch->dma->sg_bus = 0;
ch->dma->sg_map = NULL;
ch->dma->sg = NULL;
}
if (ch->dma->data_map) {
bus_dmamap_destroy(ch->dma->data_tag, ch->dma->data_map);
ch->dma->data_map = NULL;
}
if (ch->dma->sg_tag) {
bus_dma_tag_destroy(ch->dma->sg_tag);
ch->dma->sg_tag = NULL;
}
if (ch->dma->data_tag) {
bus_dma_tag_destroy(ch->dma->data_tag);
ch->dma->data_tag = NULL;
}
if (ch->dma->dmatag) {
bus_dma_tag_destroy(ch->dma->dmatag);
ch->dma->dmatag = NULL;
if (ch->dma.dmatag) {
bus_dma_tag_destroy(ch->dma.dmatag);
ch->dma.dmatag = NULL;
}
}
@ -218,67 +169,144 @@ ata_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
}
static int
ata_dmaload(device_t dev, caddr_t data, int32_t count, int dir,
void *addr, int *entries)
ata_dmaload(struct ata_request *request, void *addr, int *entries)
{
struct ata_channel *ch = device_get_softc(dev);
struct ata_dmasetprd_args cba;
struct ata_channel *ch = device_get_softc(request->parent);
struct ata_dc_cb_args dcba;
struct ata_dmasetprd_args dspa;
int error;
if (ch->dma->flags & ATA_DMA_LOADED) {
device_printf(dev, "FAILURE - already active DMA on this device\n");
ATA_DEBUG_RQ(request, "dmaload");
if (request->dma.cur_iosize) {
device_printf(request->dev,
"FAILURE - already active DMA on this device\n");
return EIO;
}
if (!count) {
device_printf(dev, "FAILURE - zero length DMA transfer attempted\n");
if (!request->bytecount) {
device_printf(request->dev,
"FAILURE - zero length DMA transfer attempted\n");
return EIO;
}
if (((uintptr_t)data & (ch->dma->alignment - 1)) ||
(count & (ch->dma->alignment - 1))) {
device_printf(dev, "FAILURE - non aligned DMA transfer attempted\n");
if (((uintptr_t)(request->data) & (ch->dma.alignment - 1)) ||
(request->bytecount & (ch->dma.alignment - 1))) {
device_printf(request->dev,
"FAILURE - non aligned DMA transfer attempted\n");
return EIO;
}
if (count > ch->dma->max_iosize) {
device_printf(dev, "FAILURE - oversized DMA transfer attempt %d > %d\n",
count, ch->dma->max_iosize);
if (request->bytecount > ch->dma.max_iosize) {
device_printf(request->dev,
"FAILURE - oversized DMA transfer attempt %d > %d\n",
request->bytecount, ch->dma.max_iosize);
return EIO;
}
cba.dmatab = addr;
if (bus_dma_tag_create(ch->dma.dmatag, PAGE_SIZE, PAGE_SIZE,
ch->dma.max_address, BUS_SPACE_MAXADDR,
NULL, NULL, MAXTABSZ, 1, MAXTABSZ,
0, NULL, NULL, &request->dma.sg_tag)) {
device_printf(request->dev, "FAILURE - create sg_tag\n");
goto error;
}
if ((error = bus_dmamap_load(ch->dma->data_tag, ch->dma->data_map,
data, count, ch->dma->setprd, &cba,
BUS_DMA_NOWAIT)) || (error = cba.error))
return error;
if (bus_dmamem_alloc(request->dma.sg_tag, (void **)&request->dma.sg, 0,
&request->dma.sg_map)) {
device_printf(request->dev, "FAILURE - alloc sg_map\n");
goto error;
}
*entries = cba.nsegs;
if (bus_dmamap_load(request->dma.sg_tag, request->dma.sg_map,
request->dma.sg, MAXTABSZ,
ata_dmasetupc_cb, &dcba, BUS_DMA_NOWAIT) || dcba.error){
bus_dmamem_free(request->dma.sg_tag,
request->dma.sg, request->dma.sg_map);
device_printf(request->dev, "FAILURE - load sg\n");
goto error;
}
request->dma.sg_bus = dcba.maddr;
bus_dmamap_sync(ch->dma->sg_tag, ch->dma->sg_map, BUS_DMASYNC_PREWRITE);
if (bus_dma_tag_create(ch->dma.dmatag, ch->dma.alignment, ch->dma.boundary,
ch->dma.max_address, BUS_SPACE_MAXADDR,
NULL, NULL, ch->dma.max_iosize,
ATA_DMA_ENTRIES, ch->dma.segsize,
BUS_DMA_ALLOCNOW, NULL, NULL,
&request->dma.data_tag)) {
device_printf(request->dev, "FAILURE - create data_tag\n");
goto error;
}
bus_dmamap_sync(ch->dma->data_tag, ch->dma->data_map,
dir ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
if (bus_dmamap_create(request->dma.data_tag, 0, &request->dma.data_map)) {
device_printf(request->dev, "FAILURE - create data_map\n");
goto error;
}
if (addr)
dspa.dmatab = addr;
else
dspa.dmatab = request->dma.sg;
if ((error = bus_dmamap_load(request->dma.data_tag, request->dma.data_map,
request->data, request->bytecount,
ch->dma.setprd, &dspa, BUS_DMA_NOWAIT)) ||
(error = dspa.error)) {
device_printf(request->dev, "FAILURE - load data\n");
goto error;
}
if (entries)
*entries = dspa.nsegs;
bus_dmamap_sync(request->dma.sg_tag, request->dma.sg_map,
BUS_DMASYNC_PREWRITE);
bus_dmamap_sync(request->dma.data_tag, request->dma.data_map,
(request->flags & ATA_R_READ) ?
BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
request->dma.cur_iosize = request->bytecount;
ch->dma->cur_iosize = count;
ch->dma->flags = dir ? (ATA_DMA_LOADED | ATA_DMA_READ) : ATA_DMA_LOADED;
return 0;
error:
ata_dmaunload(request);
return EIO;
}
int
ata_dmaunload(device_t dev)
ata_dmaunload(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(dev);
ATA_DEBUG_RQ(request, "dmaunload");
if (ch->dma->flags & ATA_DMA_LOADED) {
bus_dmamap_sync(ch->dma->sg_tag, ch->dma->sg_map,
if (request->dma.cur_iosize) {
bus_dmamap_sync(request->dma.sg_tag, request->dma.sg_map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_sync(ch->dma->data_tag, ch->dma->data_map,
(ch->dma->flags & ATA_DMA_READ) ?
bus_dmamap_sync(request->dma.data_tag, request->dma.data_map,
(request->flags & ATA_R_READ) ?
BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(ch->dma->data_tag, ch->dma->data_map);
bus_dmamap_unload(request->dma.data_tag, request->dma.data_map);
ch->dma->cur_iosize = 0;
ch->dma->flags &= ~ATA_DMA_LOADED;
request->dma.cur_iosize = 0;
}
if (request->dma.data_map) {
bus_dmamap_destroy(request->dma.data_tag, request->dma.data_map);
request->dma.data_map = NULL;
}
if (request->dma.data_tag) {
bus_dma_tag_destroy(request->dma.data_tag);
request->dma.data_tag = NULL;
}
if (request->dma.sg_bus) {
bus_dmamap_unload(request->dma.sg_tag, request->dma.sg_map);
bus_dmamem_free(request->dma.sg_tag, request->dma.sg,
request->dma.sg_map);
request->dma.sg = NULL;
request->dma.sg_bus = 0;
request->dma.sg_map = NULL;
}
if (request->dma.sg_tag) {
bus_dma_tag_destroy(request->dma.sg_tag);
request->dma.sg_tag = NULL;
}
return 0;
}

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -64,16 +64,19 @@ ata_generic_hw(device_t dev)
ch->hw.begin_transaction = ata_begin_transaction;
ch->hw.end_transaction = ata_end_transaction;
ch->hw.status = ata_generic_status;
ch->hw.softreset = NULL;
ch->hw.command = ata_generic_command;
ch->hw.tf_read = ata_tf_read;
ch->hw.tf_write = ata_tf_write;
ch->hw.pm_read = NULL;
ch->hw.pm_write = NULL;
}
/* must be called with ATA channel locked and state_mtx held */
int
ata_begin_transaction(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
int dummy, error;
@ -133,9 +136,7 @@ ata_begin_transaction(struct ata_request *request)
/* ATA DMA data transfer commands */
case ATA_R_DMA:
/* check sanity, setup SG list and DMA engine */
if ((error = ch->dma->load(ch->dev, request->data, request->bytecount,
request->flags & ATA_R_READ, ch->dma->sg,
&dummy))) {
if ((error = ch->dma.load(request, NULL, &dummy))) {
device_printf(request->dev, "setting up DMA failed\n");
request->result = error;
goto begin_finished;
@ -150,7 +151,7 @@ ata_begin_transaction(struct ata_request *request)
}
/* start DMA engine */
if (ch->dma->start && ch->dma->start(request->dev)) {
if (ch->dma.start && ch->dma.start(request)) {
device_printf(request->dev, "error starting DMA\n");
request->result = EIO;
goto begin_finished;
@ -161,7 +162,7 @@ ata_begin_transaction(struct ata_request *request)
case ATA_R_ATAPI:
/* is this just a POLL DSC command ? */
if (request->u.atapi.ccb[0] == ATAPI_POLL_DSC) {
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit);
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit));
DELAY(10);
if (!(ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_DSC))
request->result = EBUSY;
@ -180,7 +181,7 @@ ata_begin_transaction(struct ata_request *request)
case ATA_R_ATAPI|ATA_R_DMA:
/* is this just a POLL DSC command ? */
if (request->u.atapi.ccb[0] == ATAPI_POLL_DSC) {
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit);
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit));
DELAY(10);
if (!(ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_DSC))
request->result = EBUSY;
@ -188,9 +189,7 @@ ata_begin_transaction(struct ata_request *request)
}
/* check sanity, setup SG list and DMA engine */
if ((error = ch->dma->load(ch->dev, request->data, request->bytecount,
request->flags & ATA_R_READ, ch->dma->sg,
&dummy))) {
if ((error = ch->dma.load(request, NULL, &dummy))) {
device_printf(request->dev, "setting up DMA failed\n");
request->result = error;
goto begin_finished;
@ -204,7 +203,7 @@ ata_begin_transaction(struct ata_request *request)
}
/* start DMA engine */
if (ch->dma->start && ch->dma->start(request->dev)) {
if (ch->dma.start && ch->dma.start(request)) {
request->result = EIO;
goto begin_finished;
}
@ -214,8 +213,7 @@ ata_begin_transaction(struct ata_request *request)
printf("ata_begin_transaction OOPS!!!\n");
begin_finished:
if (ch->dma && ch->dma->flags & ATA_DMA_LOADED)
ch->dma->unload(ch->dev);
ch->dma.unload(request);
return ATA_OP_FINISHED;
begin_continue:
@ -228,7 +226,7 @@ ata_begin_transaction(struct ata_request *request)
int
ata_end_transaction(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
int length;
@ -314,19 +312,19 @@ ata_end_transaction(struct ata_request *request)
case ATA_R_DMA:
/* stop DMA engine and get status */
if (ch->dma->stop)
request->dmastat = ch->dma->stop(request->dev);
if (ch->dma.stop)
request->dma.status = ch->dma.stop(request);
/* did we get error or data */
if (request->status & ATA_S_ERROR)
request->error = ATA_IDX_INB(ch, ATA_ERROR);
else if (request->dmastat & ATA_BMSTAT_ERROR)
else if (request->dma.status & ATA_BMSTAT_ERROR)
request->status |= ATA_S_ERROR;
else if (!(request->flags & ATA_R_TIMEOUT))
request->donecount = request->bytecount;
/* release SG list etc */
ch->dma->unload(ch->dev);
ch->dma.unload(request);
/* done with HW */
goto end_finished;
@ -426,19 +424,19 @@ ata_end_transaction(struct ata_request *request)
case ATA_R_ATAPI|ATA_R_DMA:
/* stop DMA engine and get status */
if (ch->dma->stop)
request->dmastat = ch->dma->stop(request->dev);
if (ch->dma.stop)
request->dma.status = ch->dma.stop(request);
/* did we get error or data */
if (request->status & (ATA_S_ERROR | ATA_S_DWF))
request->error = ATA_IDX_INB(ch, ATA_ERROR);
else if (request->dmastat & ATA_BMSTAT_ERROR)
else if (request->dma.status & ATA_BMSTAT_ERROR)
request->status |= ATA_S_ERROR;
else if (!(request->flags & ATA_R_TIMEOUT))
request->donecount = request->bytecount;
/* release SG list etc */
ch->dma->unload(ch->dev);
ch->dma.unload(request);
/* done with HW */
goto end_finished;
@ -617,7 +615,7 @@ ata_wait(struct ata_channel *ch, struct ata_device *atadev, u_int8_t mask)
/* if drive fails status, reselect the drive and try again */
if (status == 0xff) {
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit);
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit));
timeout += 1000;
DELAY(1000);
continue;
@ -657,11 +655,11 @@ ata_wait(struct ata_channel *ch, struct ata_device *atadev, u_int8_t mask)
int
ata_generic_command(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
/* select device */
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | atadev->unit);
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit));
/* ready to issue command ? */
if (ata_wait(ch, atadev, 0) < 0) {
@ -728,7 +726,7 @@ ata_generic_command(struct ata_request *request)
static void
ata_tf_read(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
if (atadev->flags & ATA_D_48BIT_ACTIVE) {
@ -758,7 +756,7 @@ ata_tf_read(struct ata_request *request)
static void
ata_tf_write(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
struct ata_channel *ch = device_get_softc(request->parent);
struct ata_device *atadev = device_get_softc(request->dev);
if (atadev->flags & ATA_D_48BIT_ACTIVE) {
@ -772,7 +770,7 @@ ata_tf_write(struct ata_request *request)
ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 40);
ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_LBA | atadev->unit);
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(atadev->unit));
}
else {
ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
@ -794,7 +792,7 @@ ata_tf_write(struct ata_request *request)
(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 | atadev->unit |
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit) |
(((request->u.ata.lba% (sectors * heads)) /
sectors) & 0xf));
}
@ -803,7 +801,7 @@ ata_tf_write(struct ata_request *request)
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 | atadev->unit |
ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit) |
((request->u.ata.lba >> 24) & 0x0f));
}
}
@ -812,7 +810,7 @@ ata_tf_write(struct ata_request *request)
static void
ata_pio_read(struct ata_request *request, int length)
{
struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
struct ata_channel *ch = device_get_softc(request->parent);
int size = min(request->transfersize, length);
int resid;
@ -837,7 +835,7 @@ ata_pio_read(struct ata_request *request, int length)
static void
ata_pio_write(struct ata_request *request, int length)
{
struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
struct ata_channel *ch = device_get_softc(request->parent);
int size = min(request->transfersize, length);
int resid;

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -422,23 +422,14 @@ ata_pci_allocate(device_t dev)
return 0;
}
void
ata_pci_hw(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
ata_generic_hw(dev);
ch->hw.status = ata_pci_status;
}
int
static int
ata_pci_status(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
if ((dumping || !ata_legacy(device_get_parent(dev))) &&
ch->dma && ((ch->flags & ATA_ALWAYS_DMASTAT) ||
(ch->dma->flags & ATA_DMA_ACTIVE))) {
((ch->flags & ATA_ALWAYS_DMASTAT) ||
(ch->dma.flags & ATA_DMA_ACTIVE))) {
int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) !=
@ -455,31 +446,44 @@ ata_pci_status(device_t dev)
return 1;
}
static int
ata_pci_dmastart(device_t dev)
void
ata_pci_hw(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
ata_generic_hw(dev);
ch->hw.status = ata_pci_status;
}
static int
ata_pci_dmastart(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(request->parent);
ATA_DEBUG_RQ(request, "dmastart");
ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) |
(ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR)));
ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->sg_bus);
ch->dma->flags |= ATA_DMA_ACTIVE;
ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, request->dma.sg_bus);
ch->dma.flags |= ATA_DMA_ACTIVE;
ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
(ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_WRITE_READ) |
((ch->dma->flags & ATA_DMA_READ) ? ATA_BMCMD_WRITE_READ : 0) |
((request->flags & ATA_R_READ) ? ATA_BMCMD_WRITE_READ : 0)|
ATA_BMCMD_START_STOP);
return 0;
}
static int
ata_pci_dmastop(device_t dev)
ata_pci_dmastop(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(request->parent);
int error;
ATA_DEBUG_RQ(request, "dmastop");
ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP);
ch->dma->flags &= ~ATA_DMA_ACTIVE;
ch->dma.flags &= ~ATA_DMA_ACTIVE;
error = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR);
return error;
@ -489,12 +493,16 @@ static void
ata_pci_dmareset(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
struct ata_request *request;
ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP);
ch->dma->flags &= ~ATA_DMA_ACTIVE;
ch->dma.flags &= ~ATA_DMA_ACTIVE;
ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR);
ch->dma->unload(dev);
if ((request = ch->running)) {
device_printf(request->dev, "DMA reset calling unload\n");
ch->dma.unload(request);
}
}
void
@ -503,11 +511,9 @@ ata_pci_dmainit(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
ata_dmainit(dev);
if (ch->dma) {
ch->dma->start = ata_pci_dmastart;
ch->dma->stop = ata_pci_dmastop;
ch->dma->reset = ata_pci_dmareset;
}
ch->dma.start = ata_pci_dmastart;
ch->dma.stop = ata_pci_dmastop;
ch->dma.reset = ata_pci_dmareset;
}
char *
@ -603,14 +609,13 @@ ata_pcichannel_attach(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
int error;
if (ctlr->dmainit)
if (ctlr->dmainit) {
ctlr->dmainit(dev);
if (ch->dma)
ch->dma->alloc(dev);
ch->dma.alloc(dev);
}
if ((error = ctlr->allocate(dev))) {
if (ch->dma)
ch->dma->free(dev);
ch->dma.free(dev);
return error;
}
@ -626,8 +631,7 @@ ata_pcichannel_detach(device_t dev)
if ((error = ata_detach(dev)))
return error;
if (ch->dma)
ch->dma->free(dev);
ch->dma.free(dev);
/* XXX SOS free resources for io and ctlio ?? */
@ -653,11 +657,8 @@ ata_pcichannel_reset(device_t dev)
struct ata_channel *ch = device_get_softc(dev);
/* if DMA engine present reset it */
if (ch->dma) {
if (ch->dma->reset)
ch->dma->reset(dev);
ch->dma->unload(dev);
}
if (ch->dma.reset)
ch->dma.reset(dev);
/* reset the controller HW */
if (ctlr->reset)

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2003 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 2003 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -460,7 +460,6 @@ int ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, int f
int ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie);
int ata_pci_allocate(device_t dev);
void ata_pci_hw(device_t dev);
int ata_pci_status(device_t dev);
void ata_pci_dmainit(device_t dev);
char *ata_pcivendor2str(device_t dev);

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -358,8 +358,8 @@ ata_completed(void *context, int dummy)
"\4MEDIA_CHANGE_REQEST"
"\3ABORTED\2NO_MEDIA\1ILLEGAL_LENGTH");
if ((request->flags & ATA_R_DMA) &&
(request->dmastat & ATA_BMSTAT_ERROR))
printf(" dma=0x%02x", request->dmastat);
(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");
@ -694,11 +694,13 @@ ata_cmd2str(struct ata_request *request)
case 0x24: return ("READ48");
case 0x25: return ("READ_DMA48");
case 0x26: return ("READ_DMA_QUEUED48");
case 0x27: return ("READ_NATIVE_MAX_ADDRESS48");
case 0x29: return ("READ_MUL48");
case 0x30: return ("WRITE");
case 0x34: return ("WRITE48");
case 0x35: return ("WRITE_DMA48");
case 0x36: return ("WRITE_DMA_QUEUED48");
case 0x37: return ("SET_MAX_ADDRESS48");
case 0x39: return ("WRITE_MUL48");
case 0x70: return ("SEEK");
case 0xa0: return ("PACKET_CMD");
@ -727,6 +729,9 @@ ata_cmd2str(struct ata_request *request)
}
sprintf(buffer, "SETFEATURES 0x%02x", request->u.ata.feature);
return buffer;
case 0xf5: return ("SECURITY_FREE_LOCK");
case 0xf8: return ("READ_NATIVE_MAX_ADDRESS");
case 0xf9: return ("SET_MAX_ADDRESS");
}
}
sprintf(buffer, "unknown CMD (0x%02x)", request->u.ata.command);

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2000 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 2000 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2000 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 2000 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2006 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 2006 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
#include <sys/ata.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/sysctl.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/sema.h>

View File

@ -1,4 +1,4 @@
# Copyright (c) 2004 - 2007 Søren Schmidt <sos@FreeBSD.org>
# Copyright (c) 2004 - 2008 Søren Schmidt <sos@FreeBSD.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -908,10 +908,7 @@ acd_set_ioparm(device_t dev)
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct acd_softc *cdp = device_get_ivars(dev);
if (ch->dma)
cdp->iomax = min(ch->dma->max_iosize, 65534);
else
cdp->iomax = min(DFLTPHYS, 65534);
cdp->iomax = min(ch->dma.max_iosize, 65534);
}
static void
@ -1706,8 +1703,7 @@ acd_describe(device_t dev)
(cdp->cap.media & MST_WRITE_CDRW) ? "CDRW" :
(cdp->cap.media & MST_WRITE_CDR) ? "CDR" :
(cdp->cap.media & MST_READ_DVDROM) ? "DVDROM":"CDROM",
device_get_unit(ch->dev),
(atadev->unit == ATA_MASTER) ? "master" : "slave");
device_get_unit(ch->dev), ata_unit2str(atadev));
device_printf(dev, "%s", "");
if (cdp->cap.cur_read_speed) {
@ -1879,8 +1875,7 @@ acd_describe(device_t dev)
printf("with %d CD changer ", cdp->changer_info->slots);
printf("<%.40s/%.8s> at ata%d-%s %s\n",
atadev->param.model, atadev->param.revision,
device_get_unit(ch->dev),
(atadev->unit == ATA_MASTER) ? "master" : "slave",
device_get_unit(ch->dev), ata_unit2str(atadev),
ata_mode2str(atadev->mode) );
}
}

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -105,10 +105,7 @@ afd_attach(device_t dev)
fdp->disk->d_ioctl = afd_ioctl;
fdp->disk->d_name = "afd";
fdp->disk->d_drv1 = dev;
if (ch->dma)
fdp->disk->d_maxsize = ch->dma->max_iosize;
else
fdp->disk->d_maxsize = DFLTPHYS;
fdp->disk->d_maxsize = ch->dma.max_iosize;
fdp->disk->d_unit = device_get_unit(dev);
disk_create(fdp->disk, DISK_VERSION);
return 0;
@ -406,8 +403,7 @@ afd_describe(device_t dev)
device_printf(dev, "%s <%.40s %.8s> at ata%d-%s %s\n",
sizestring, atadev->param.model, atadev->param.revision,
device_get_unit(ch->dev),
(atadev->unit == ATA_MASTER) ? "master" : "slave",
device_get_unit(ch->dev), ata_unit2str(atadev),
ata_mode2str(atadev->mode));
if (bootverbose) {
device_printf(dev, "%ju sectors [%juC/%dH/%dS]\n",

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -142,19 +142,13 @@ ast_attach(device_t dev)
UID_ROOT, GID_OPERATOR, 0640, "ast%d",
device_get_unit(dev));
device->si_drv1 = dev;
if (ch->dma)
device->si_iosize_max = ch->dma->max_iosize;
else
device->si_iosize_max = DFLTPHYS;
device->si_iosize_max = ch->dma.max_iosize;
stp->dev1 = device;
device = make_dev(&ast_cdevsw, 2 * device_get_unit(dev) + 1,
UID_ROOT, GID_OPERATOR, 0640, "nast%d",
device_get_unit(dev));
device->si_drv1 = dev;
if (ch->dma)
device->si_iosize_max = ch->dma->max_iosize;
else
device->si_iosize_max = DFLTPHYS;
device->si_iosize_max = ch->dma.max_iosize;
stp->dev2 = device;
/* announce we are here and ready */
@ -678,8 +672,7 @@ ast_describe(device_t 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),
(atadev->unit == ATA_MASTER) ? "master" : "slave");
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" : "");
@ -717,8 +710,7 @@ ast_describe(device_t dev)
else {
device_printf(dev, "TAPE <%.40s/%.8s> at ata%d-%s %s\n",
atadev->param.model, atadev->param.revision,
device_get_unit(ch->dev),
(atadev->unit == ATA_MASTER) ? "master" : "slave",
device_get_unit(ch->dev), ata_unit2str(atadev),
ata_mode2str(atadev->mode));
}
}

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2000 - 2006 Søren Schmidt <sos@FreeBSD.org>
* Copyright (c) 2000 - 2008 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -239,7 +239,7 @@ struct ata_params {
#define ATA_READ48 0x24 /* read 48bit LBA */
#define ATA_READ_DMA48 0x25 /* read DMA 48bit LBA */
#define ATA_READ_DMA_QUEUED48 0x26 /* read DMA QUEUED 48bit LBA */
#define ATA_READ_NATIVE_MAX_ADDDRESS48 0x27 /* read native max addr 48bit */
#define ATA_READ_NATIVE_MAX_ADDRESS48 0x27 /* read native max addr 48bit */
#define ATA_READ_MUL48 0x29 /* read multi 48bit LBA */
#define ATA_WRITE 0x30 /* write */
#define ATA_WRITE48 0x34 /* write 48bit LBA */
@ -267,8 +267,10 @@ struct ata_params {
#define ATA_STANDBY_CMD 0xe2 /* standby */
#define ATA_IDLE_CMD 0xe3 /* idle */
#define ATA_READ_BUFFER 0xe4 /* read buffer */
#define ATA_READ_PM 0xe4 /* read portmultiplier */
#define ATA_SLEEP 0xe6 /* sleep */
#define ATA_FLUSHCACHE 0xe7 /* flush cache to disk */
#define ATA_WRITE_PM 0xe8 /* write portmultiplier */
#define ATA_FLUSHCACHE48 0xea /* flush cache to disk */
#define ATA_ATA_IDENTIFY 0xec /* get ATA params */
#define ATA_SETFEATURES 0xef /* features command */
@ -282,7 +284,7 @@ struct ata_params {
#define ATA_SF_ENAB_SRVIRQ 0x5e /* enable service interrupt */
#define ATA_SF_DIS_SRVIRQ 0xde /* disable service interrupt */
#define ATA_SECURITY_FREEE_LOCK 0xf5 /* freeze security config */
#define ATA_READ_NATIVE_MAX_ADDDRESS 0xf8 /* read native max address */
#define ATA_READ_NATIVE_MAX_ADDRESS 0xf8 /* read native max address */
#define ATA_SET_MAX_ADDRESS 0xf9 /* set max address */