Properly support the 3ware generic API.
- Build SGL's for ATA_PASSTHROUGH commands - Fallback to using the sgl_offset when the opcode is unknown for building SGL's/ - Add ioctl calls for adding and removing units. - Define previously undefined AEN's - Allocate memory for the ioctl payload in multiples of 512bytes. MFC after: 1 week
This commit is contained in:
parent
9a3ea63e79
commit
235a79707a
@ -60,6 +60,8 @@ static int twe_wait_request(struct twe_request *tr);
|
||||
static int twe_immediate_request(struct twe_request *tr);
|
||||
static void twe_completeio(struct twe_request *tr);
|
||||
static void twe_reset(struct twe_softc *sc);
|
||||
static void twe_add_unit(struct twe_softc *sc, int unit);
|
||||
static void twe_del_unit(struct twe_softc *sc, int unit);
|
||||
|
||||
/*
|
||||
* Command I/O to controller.
|
||||
@ -189,18 +191,17 @@ twe_setup(struct twe_softc *sc)
|
||||
return(0);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Locate disk devices and attach children to them.
|
||||
*/
|
||||
void
|
||||
twe_init(struct twe_softc *sc)
|
||||
static void
|
||||
twe_add_unit(struct twe_softc *sc, int unit)
|
||||
{
|
||||
struct twe_drive *dr;
|
||||
int i, table;
|
||||
int table;
|
||||
u_int16_t dsize;
|
||||
TWE_Param *drives, *param;
|
||||
TWE_Param *drives = NULL, *param = NULL;
|
||||
TWE_Unit_Descriptor *ud;
|
||||
|
||||
if (unit < 0 || unit > TWE_MAX_UNITS)
|
||||
return;
|
||||
|
||||
/*
|
||||
* The controller is in a safe state, so try to find drives attached to it.
|
||||
@ -210,52 +211,76 @@ twe_init(struct twe_softc *sc)
|
||||
twe_printf(sc, "can't detect attached units\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* For each detected unit, create a child device.
|
||||
*/
|
||||
for (i = 0, dr = &sc->twe_drive[0]; i < TWE_MAX_UNITS; i++, dr++) {
|
||||
|
||||
/* check that the drive is online */
|
||||
if (!(drives->data[i] & TWE_PARAM_UNITSTATUS_Online))
|
||||
continue;
|
||||
dr = &sc->twe_drive[unit];
|
||||
/* check that the drive is online */
|
||||
if (!(drives->data[unit] & TWE_PARAM_UNITSTATUS_Online))
|
||||
goto out;
|
||||
|
||||
table = TWE_PARAM_UNITINFO + i;
|
||||
table = TWE_PARAM_UNITINFO + unit;
|
||||
|
||||
if (twe_get_param_4(sc, table, TWE_PARAM_UNITINFO_Capacity, &dr->td_size)) {
|
||||
twe_printf(sc, "error fetching capacity for unit %d\n", i);
|
||||
continue;
|
||||
}
|
||||
if (twe_get_param_1(sc, table, TWE_PARAM_UNITINFO_Status, &dr->td_state)) {
|
||||
twe_printf(sc, "error fetching state for unit %d\n", i);
|
||||
continue;
|
||||
}
|
||||
if (twe_get_param_2(sc, table, TWE_PARAM_UNITINFO_DescriptorSize, &dsize)) {
|
||||
twe_printf(sc, "error fetching descriptor size for unit %d\n", i);
|
||||
continue;
|
||||
}
|
||||
if ((param = twe_get_param(sc, table, TWE_PARAM_UNITINFO_Descriptor, dsize - 3, NULL)) == NULL) {
|
||||
twe_printf(sc, "error fetching descriptor for unit %d\n", i);
|
||||
continue;
|
||||
}
|
||||
ud = (TWE_Unit_Descriptor *)param->data;
|
||||
dr->td_type = ud->configuration;
|
||||
free(param, M_DEVBUF);
|
||||
|
||||
/* build synthetic geometry as per controller internal rules */
|
||||
if (dr->td_size > 0x200000) {
|
||||
dr->td_heads = 255;
|
||||
dr->td_sectors = 63;
|
||||
} else {
|
||||
dr->td_heads = 64;
|
||||
dr->td_sectors = 32;
|
||||
}
|
||||
dr->td_cylinders = dr->td_size / (dr->td_heads * dr->td_sectors);
|
||||
dr->td_unit = i;
|
||||
|
||||
twe_attach_drive(sc, dr);
|
||||
if (twe_get_param_4(sc, table, TWE_PARAM_UNITINFO_Capacity, &dr->td_size)) {
|
||||
twe_printf(sc, "error fetching capacity for unit %d\n", unit);
|
||||
goto out;
|
||||
}
|
||||
free(drives, M_DEVBUF);
|
||||
if (twe_get_param_1(sc, table, TWE_PARAM_UNITINFO_Status, &dr->td_state)) {
|
||||
twe_printf(sc, "error fetching state for unit %d\n", unit);
|
||||
goto out;
|
||||
}
|
||||
if (twe_get_param_2(sc, table, TWE_PARAM_UNITINFO_DescriptorSize, &dsize)) {
|
||||
twe_printf(sc, "error fetching descriptor size for unit %d\n", unit);
|
||||
goto out;
|
||||
}
|
||||
if ((param = twe_get_param(sc, table, TWE_PARAM_UNITINFO_Descriptor, dsize - 3, NULL)) == NULL) {
|
||||
twe_printf(sc, "error fetching descriptor for unit %d\n", unit);
|
||||
goto out;
|
||||
}
|
||||
ud = (TWE_Unit_Descriptor *)param->data;
|
||||
dr->td_type = ud->configuration;
|
||||
|
||||
/* build synthetic geometry as per controller internal rules */
|
||||
if (dr->td_size > 0x200000) {
|
||||
dr->td_heads = 255;
|
||||
dr->td_sectors = 63;
|
||||
} else {
|
||||
dr->td_heads = 64;
|
||||
dr->td_sectors = 32;
|
||||
}
|
||||
dr->td_cylinders = dr->td_size / (dr->td_heads * dr->td_sectors);
|
||||
dr->td_unit = unit;
|
||||
|
||||
twe_attach_drive(sc, dr);
|
||||
|
||||
out:
|
||||
if (param != NULL)
|
||||
free(param, M_DEVBUF);
|
||||
if (drives != NULL)
|
||||
free(drives, M_DEVBUF);
|
||||
}
|
||||
|
||||
static void
|
||||
twe_del_unit(struct twe_softc *sc, int unit)
|
||||
{
|
||||
|
||||
if (unit < 0 || unit > TWE_MAX_UNITS)
|
||||
return;
|
||||
|
||||
twe_detach_drive(sc, unit);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Locate disk devices and attach children to them.
|
||||
*/
|
||||
void
|
||||
twe_init(struct twe_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Scan for drives
|
||||
*/
|
||||
for (i = 0; i < TWE_MAX_UNITS; i++)
|
||||
twe_add_unit(sc, i);
|
||||
|
||||
/*
|
||||
* Initialise connection with controller.
|
||||
@ -447,6 +472,7 @@ twe_ioctl(struct twe_softc *sc, int cmd, void *addr)
|
||||
{
|
||||
struct twe_usercommand *tu = (struct twe_usercommand *)addr;
|
||||
struct twe_paramcommand *tp = (struct twe_paramcommand *)addr;
|
||||
struct twe_drivecommand *td = (struct twe_drivecommand *)addr;
|
||||
union twe_statrequest *ts = (union twe_statrequest *)addr;
|
||||
TWE_Param *param;
|
||||
void *data;
|
||||
@ -460,10 +486,8 @@ twe_ioctl(struct twe_softc *sc, int cmd, void *addr)
|
||||
/* handle a command from userspace */
|
||||
case TWEIO_COMMAND:
|
||||
/* get a request */
|
||||
if (twe_get_request(sc, &tr)) {
|
||||
error = EBUSY;
|
||||
goto cmd_done;
|
||||
}
|
||||
while (twe_get_request(sc, &tr))
|
||||
tsleep(NULL, PPAUSE, "twioctl", hz);
|
||||
|
||||
/*
|
||||
* Save the command's request ID, copy the user-supplied command in,
|
||||
@ -473,14 +497,17 @@ twe_ioctl(struct twe_softc *sc, int cmd, void *addr)
|
||||
bcopy(&tu->tu_command, &tr->tr_command, sizeof(TWE_Command));
|
||||
tr->tr_command.generic.request_id = srid;
|
||||
|
||||
/* if there's a data buffer, allocate and copy it in */
|
||||
tr->tr_length = tu->tu_size;
|
||||
/*
|
||||
* if there's a data buffer, allocate and copy it in.
|
||||
* Must be in multipled of 512 bytes.
|
||||
*/
|
||||
tr->tr_length = (tu->tu_size + 511) & ~511;
|
||||
if (tr->tr_length > 0) {
|
||||
if ((tr->tr_data = malloc(tr->tr_length, M_DEVBUF, M_WAITOK)) == NULL) {
|
||||
error = ENOMEM;
|
||||
goto cmd_done;
|
||||
}
|
||||
if ((error = copyin(tu->tu_data, tr->tr_data, tr->tr_length)) != 0)
|
||||
if ((error = copyin(tu->tu_data, tr->tr_data, tu->tu_size)) != 0)
|
||||
goto cmd_done;
|
||||
tr->tr_flags |= TWE_CMD_DATAIN | TWE_CMD_DATAOUT;
|
||||
}
|
||||
@ -494,7 +521,7 @@ twe_ioctl(struct twe_softc *sc, int cmd, void *addr)
|
||||
|
||||
/* if there was a data buffer, copy it out */
|
||||
if (tr->tr_length > 0)
|
||||
error = copyout(tr->tr_data, tu->tu_data, tr->tr_length);
|
||||
error = copyout(tr->tr_data, tu->tu_data, tu->tu_size);
|
||||
|
||||
cmd_done:
|
||||
/* free resources */
|
||||
@ -526,14 +553,12 @@ twe_ioctl(struct twe_softc *sc, int cmd, void *addr)
|
||||
/* poll for an AEN */
|
||||
case TWEIO_AEN_POLL:
|
||||
*arg = twe_dequeue_aen(sc);
|
||||
if (*arg == -1)
|
||||
error = ENOENT;
|
||||
break;
|
||||
|
||||
/* wait for another AEN to show up */
|
||||
case TWEIO_AEN_WAIT:
|
||||
s = splbio();
|
||||
while ((*arg = twe_dequeue_aen(sc)) == -1) {
|
||||
while ((*arg = twe_dequeue_aen(sc)) == TWE_AEN_QUEUE_EMPTY) {
|
||||
error = tsleep(&sc->twe_aen_queue, PRIBIO | PCATCH, "tweaen", 0);
|
||||
if (error == EINTR)
|
||||
break;
|
||||
@ -573,6 +598,14 @@ twe_ioctl(struct twe_softc *sc, int cmd, void *addr)
|
||||
twe_reset(sc);
|
||||
break;
|
||||
|
||||
case TWEIO_ADD_UNIT:
|
||||
twe_add_unit(sc, td->td_unit);
|
||||
break;
|
||||
|
||||
case TWEIO_DEL_UNIT:
|
||||
twe_del_unit(sc, td->td_unit);
|
||||
break;
|
||||
|
||||
/* XXX implement ATA PASSTHROUGH */
|
||||
|
||||
/* nothing we understand */
|
||||
@ -1394,7 +1427,7 @@ twe_dequeue_aen(struct twe_softc *sc)
|
||||
debug_called(4);
|
||||
|
||||
if (sc->twe_aen_tail == sc->twe_aen_head) {
|
||||
result = -1;
|
||||
result = TWE_AEN_QUEUE_EMPTY;
|
||||
} else {
|
||||
result = sc->twe_aen_queue[sc->twe_aen_tail];
|
||||
sc->twe_aen_tail = ((sc->twe_aen_tail + 1) % TWE_Q_LENGTH);
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
@ -113,7 +114,9 @@
|
||||
bus_dma_tag_t twe_buffer_dmat; /* data buffer DMA tag */ \
|
||||
struct resource *twe_irq; /* interrupt */ \
|
||||
void *twe_intr; /* interrupt handle */ \
|
||||
struct intr_config_hook twe_ich; /* delayed-startup hook */
|
||||
struct intr_config_hook twe_ich; /* delayed-startup hook */ \
|
||||
struct sysctl_ctx_list sysctl_ctx; \
|
||||
struct sysctl_oid *sysctl_tree;
|
||||
|
||||
/*
|
||||
* FreeBSD-specific request elements
|
||||
|
@ -124,7 +124,7 @@ static int twe_probe(device_t dev);
|
||||
static int twe_attach(device_t dev);
|
||||
static void twe_free(struct twe_softc *sc);
|
||||
static int twe_detach(device_t dev);
|
||||
static int twe_shutdown(device_t dev);
|
||||
static void twe_shutdown(device_t dev);
|
||||
static int twe_suspend(device_t dev);
|
||||
static int twe_resume(device_t dev);
|
||||
static void twe_pci_intr(void *arg);
|
||||
@ -196,6 +196,18 @@ twe_attach(device_t dev)
|
||||
sc = device_get_softc(dev);
|
||||
sc->twe_dev = dev;
|
||||
|
||||
sysctl_ctx_init(&sc->sysctl_ctx);
|
||||
sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
|
||||
SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
|
||||
device_get_nameunit(dev), CTLFLAG_RD, 0, "");
|
||||
if (sc->sysctl_tree == NULL) {
|
||||
twe_printf(sc, "cannot add sysctl tree node\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
SYSCTL_ADD_STRING(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
|
||||
OID_AUTO, "driver_version", CTLFLAG_RD, "$Revision$", 0,
|
||||
"TWE driver version");
|
||||
|
||||
/*
|
||||
* Make sure we are going to be able to talk to this board.
|
||||
*/
|
||||
@ -346,6 +358,8 @@ twe_free(struct twe_softc *sc)
|
||||
/* destroy control device */
|
||||
if (sc->twe_dev_t != (dev_t)NULL)
|
||||
destroy_dev(sc->twe_dev_t);
|
||||
|
||||
sysctl_ctx_free(&sc->sysctl_ctx);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
@ -367,8 +381,7 @@ twe_detach(device_t dev)
|
||||
/*
|
||||
* Shut the controller down.
|
||||
*/
|
||||
if ((error = twe_shutdown(dev)))
|
||||
goto out;
|
||||
twe_shutdown(dev);
|
||||
|
||||
twe_free(sc);
|
||||
|
||||
@ -384,26 +397,21 @@ twe_detach(device_t dev)
|
||||
* Note that we can assume that the bioq on the controller is empty, as we won't
|
||||
* allow shutdown if any device is open.
|
||||
*/
|
||||
static int
|
||||
static void
|
||||
twe_shutdown(device_t dev)
|
||||
{
|
||||
struct twe_softc *sc = device_get_softc(dev);
|
||||
int i, s, error;
|
||||
int i, s;
|
||||
|
||||
debug_called(4);
|
||||
|
||||
s = splbio();
|
||||
error = 0;
|
||||
|
||||
/*
|
||||
* Delete all our child devices.
|
||||
*/
|
||||
for (i = 0; i < TWE_MAX_UNITS; i++) {
|
||||
if (sc->twe_drive[i].td_disk != 0) {
|
||||
if ((error = device_delete_child(sc->twe_dev, sc->twe_drive[i].td_disk)) != 0)
|
||||
goto out;
|
||||
sc->twe_drive[i].td_disk = 0;
|
||||
}
|
||||
twe_detach_drive(sc, i);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -411,9 +419,7 @@ twe_shutdown(device_t dev)
|
||||
*/
|
||||
twe_deinit(sc);
|
||||
|
||||
out:
|
||||
splx(s);
|
||||
return(error);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
@ -480,7 +486,7 @@ twe_intrhook(void *arg)
|
||||
/********************************************************************************
|
||||
* Given a detected drive, attach it to the bio interface.
|
||||
*
|
||||
* This is called from twe_init.
|
||||
* This is called from twe_add_unit.
|
||||
*/
|
||||
void
|
||||
twe_attach_drive(struct twe_softc *sc, struct twe_drive *dr)
|
||||
@ -499,7 +505,9 @@ twe_attach_drive(struct twe_softc *sc, struct twe_drive *dr)
|
||||
* XXX It would make sense to test the online/initialising bits, but they seem to be
|
||||
* always set...
|
||||
*/
|
||||
sprintf(buf, "%s, %s", twe_describe_code(twe_table_unittype, dr->td_type),
|
||||
sprintf(buf, "Unit %d, %s, %s",
|
||||
dr->td_unit,
|
||||
twe_describe_code(twe_table_unittype, dr->td_type),
|
||||
twe_describe_code(twe_table_unitstate, dr->td_state & TWE_PARAM_UNITSTATUS_MASK));
|
||||
device_set_desc_copy(dr->td_disk, buf);
|
||||
|
||||
@ -507,6 +515,22 @@ twe_attach_drive(struct twe_softc *sc, struct twe_drive *dr)
|
||||
twe_printf(sc, "bus_generic_attach returned %d\n", error);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Detach the specified unit if it exsists
|
||||
*
|
||||
* This is called from twe_del_unit.
|
||||
*/
|
||||
void
|
||||
twe_detach_drive(struct twe_softc *sc, int unit)
|
||||
{
|
||||
|
||||
if (sc->twe_drive[unit].td_disk != 0) {
|
||||
if (device_delete_child(sc->twe_dev, sc->twe_drive[unit].td_disk) != 0)
|
||||
twe_printf(sc, "failed to delete unit %d\n", unit);
|
||||
sc->twe_drive[unit].td_disk = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Clear a PCI parity error.
|
||||
*/
|
||||
@ -812,12 +836,26 @@ twe_free_request(struct twe_request *tr)
|
||||
* fashion. Due to a hardware limitation, I/O buffers must be 512-byte aligned
|
||||
* and we take care of that here as well.
|
||||
*/
|
||||
static void
|
||||
twe_fillin_sgl(TWE_SG_Entry *sgl, bus_dma_segment_t *segs, int nsegments, int max_sgl)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nsegments; i++) {
|
||||
sgl[i].address = segs[i].ds_addr;
|
||||
sgl[i].length = segs[i].ds_len;
|
||||
}
|
||||
for (; i < max_sgl; i++) { /* XXX necessary? */
|
||||
sgl[i].address = 0;
|
||||
sgl[i].length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
twe_setup_data_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
|
||||
{
|
||||
struct twe_request *tr = (struct twe_request *)arg;
|
||||
TWE_Command *cmd = &tr->tr_command;
|
||||
int i;
|
||||
|
||||
debug_called(4);
|
||||
|
||||
@ -836,30 +874,35 @@ twe_setup_data_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int err
|
||||
case TWE_OP_GET_PARAM:
|
||||
case TWE_OP_SET_PARAM:
|
||||
cmd->generic.sgl_offset = 2;
|
||||
for (i = 0; i < nsegments; i++) {
|
||||
cmd->param.sgl[i].address = segs[i].ds_addr;
|
||||
cmd->param.sgl[i].length = segs[i].ds_len;
|
||||
}
|
||||
for (; i < TWE_MAX_SGL_LENGTH; i++) { /* XXX necessary? */
|
||||
cmd->param.sgl[i].address = 0;
|
||||
cmd->param.sgl[i].length = 0;
|
||||
}
|
||||
twe_fillin_sgl(&cmd->param.sgl[0], segs, nsegments, TWE_MAX_SGL_LENGTH);
|
||||
break;
|
||||
case TWE_OP_READ:
|
||||
case TWE_OP_WRITE:
|
||||
cmd->generic.sgl_offset = 3;
|
||||
for (i = 0; i < nsegments; i++) {
|
||||
cmd->io.sgl[i].address = segs[i].ds_addr;
|
||||
cmd->io.sgl[i].length = segs[i].ds_len;
|
||||
}
|
||||
for (; i < TWE_MAX_SGL_LENGTH; i++) { /* XXX necessary? */
|
||||
cmd->io.sgl[i].address = 0;
|
||||
cmd->io.sgl[i].length = 0;
|
||||
}
|
||||
twe_fillin_sgl(&cmd->io.sgl[0], segs, nsegments, TWE_MAX_SGL_LENGTH);
|
||||
break;
|
||||
case TWE_OP_ATA_PASSTHROUGH:
|
||||
cmd->generic.sgl_offset = 5;
|
||||
twe_fillin_sgl(&cmd->ata.sgl[0], segs, nsegments, TWE_MAX_ATA_SGL_LENGTH);
|
||||
break;
|
||||
default:
|
||||
/* no s/g list, nothing to do */
|
||||
break;
|
||||
/*
|
||||
* Fall back to what the linux driver does.
|
||||
* Do this because the API may send an opcode
|
||||
* the driver knows nothing about and this will
|
||||
* at least stop PCIABRT's from hosing us.
|
||||
*/
|
||||
switch (cmd->generic.sgl_offset) {
|
||||
case 2:
|
||||
twe_fillin_sgl(&cmd->param.sgl[0], segs, nsegments, TWE_MAX_SGL_LENGTH);
|
||||
break;
|
||||
case 3:
|
||||
twe_fillin_sgl(&cmd->io.sgl[0], segs, nsegments, TWE_MAX_SGL_LENGTH);
|
||||
break;
|
||||
case 5:
|
||||
twe_fillin_sgl(&cmd->ata.sgl[0], segs, nsegments, TWE_MAX_ATA_SGL_LENGTH);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,6 +143,9 @@ struct twe_code_lookup twe_table_aen[] = {
|
||||
{"c verify complete", 0x2b},
|
||||
{"p overwrote bad sector during rebuild", 0x2c},
|
||||
{"p encountered bad sector during rebuild", 0x2d},
|
||||
{"a replacement drive too small", 0x2e},
|
||||
{"c array not previously initialized", 0x2f},
|
||||
{"p drive not supported", 0x30},
|
||||
{"a aen queue full", 0xff},
|
||||
{NULL, 0},
|
||||
{"x unknown AEN", 0}
|
||||
|
@ -90,3 +90,13 @@ struct twe_paramcommand {
|
||||
* Request a controller soft-reset
|
||||
*/
|
||||
#define TWEIO_RESET _IO ('T', 106)
|
||||
|
||||
/*
|
||||
* Request a drive addition or deletion
|
||||
*/
|
||||
struct twe_drivecommand {
|
||||
int td_unit;
|
||||
};
|
||||
|
||||
#define TWEIO_ADD_UNIT _IOW ('U', 107, int)
|
||||
#define TWEIO_DEL_UNIT _IOW ('U', 108, int)
|
||||
|
@ -119,6 +119,7 @@
|
||||
#define TWE_OP_FLUSH 0x0e
|
||||
#define TWE_OP_ABORT 0x0f
|
||||
#define TWE_OP_CHECKSTATUS 0x10
|
||||
#define TWE_OP_ATA_PASSTHROUGH 0x11
|
||||
#define TWE_OP_GET_PARAM 0x12
|
||||
#define TWE_OP_SET_PARAM 0x13
|
||||
#define TWE_OP_CREATEUNIT 0x14
|
||||
@ -127,7 +128,6 @@
|
||||
#define TWE_OP_SECTOR_INFO 0x1a
|
||||
#define TWE_OP_AEN_LISTEN 0x1c
|
||||
#define TWE_OP_CMD_PACKET 0x1d
|
||||
#define TWE_OP_ATA_PASSTHROUGH 0x1e
|
||||
#define TWE_OP_CMD_WITH_DATA 0x1f
|
||||
|
||||
/* command status values */
|
||||
|
@ -144,7 +144,9 @@ extern void twe_enable_interrupts(struct twe_softc *sc); /* enable controller in
|
||||
extern void twe_disable_interrupts(struct twe_softc *sc); /* disable controller interrupts */
|
||||
|
||||
extern void twe_attach_drive(struct twe_softc *sc,
|
||||
struct twe_drive *dr); /* attach drive when found in twe_init */
|
||||
struct twe_drive *dr); /* attach drive when found in twe_add_unit */
|
||||
extern void twe_detach_drive(struct twe_softc *sc,
|
||||
int unit); /* detach drive */
|
||||
extern void twe_clear_pci_parity_error(struct twe_softc *sc);
|
||||
extern void twe_clear_pci_abort(struct twe_softc *sc);
|
||||
extern void twed_intr(twe_bio *bp); /* return bio from core */
|
||||
|
Loading…
x
Reference in New Issue
Block a user