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:
parent
3cba562fb9
commit
9f82379c24
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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) );
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user