summaryrefslogtreecommitdiffstats
path: root/sys/dev/twe/twe.c
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2003-08-12 06:38:55 +0000
committerps <ps@FreeBSD.org>2003-08-12 06:38:55 +0000
commit1bff6686ac1f910b42d321c4b6aeed66c70f7a4d (patch)
treeef44b15d650aa36cef07ac360c95a3df64d9c9e3 /sys/dev/twe/twe.c
parent1a2d5f38b0e6fb77c067fe3f08059dd9293ab98b (diff)
downloadFreeBSD-src-1bff6686ac1f910b42d321c4b6aeed66c70f7a4d.zip
FreeBSD-src-1bff6686ac1f910b42d321c4b6aeed66c70f7a4d.tar.gz
Fix the busdma support in twe to support EINPROGRESS and enable it for
use with PAE kernels.
Diffstat (limited to 'sys/dev/twe/twe.c')
-rw-r--r--sys/dev/twe/twe.c105
1 files changed, 52 insertions, 53 deletions
diff --git a/sys/dev/twe/twe.c b/sys/dev/twe/twe.c
index e2f5ff1..59c737f 100644
--- a/sys/dev/twe/twe.c
+++ b/sys/dev/twe/twe.c
@@ -66,7 +66,6 @@ static void twe_del_unit(struct twe_softc *sc, int unit);
/*
* Command I/O to controller.
*/
-static int twe_start(struct twe_request *tr);
static void twe_done(struct twe_softc *sc);
static void twe_complete(struct twe_softc *sc);
static int twe_wait_status(struct twe_softc *sc, u_int32_t status, int timeout);
@@ -117,6 +116,7 @@ int
twe_setup(struct twe_softc *sc)
{
struct twe_request *tr;
+ TWE_Command *cmd;
u_int32_t status_reg;
int i;
@@ -136,13 +136,14 @@ twe_setup(struct twe_softc *sc)
* Allocate request structures up front.
*/
for (i = 0; i < TWE_Q_LENGTH; i++) {
- if ((tr = twe_allocate_request(sc)) == NULL)
+ if ((tr = twe_allocate_request(sc, i)) == NULL)
return(ENOMEM);
/*
* Set global defaults that won't change.
*/
- tr->tr_command.generic.host_id = sc->twe_host_id; /* controller-assigned host ID */
- tr->tr_command.generic.request_id = i; /* our index number */
+ cmd = TWE_FIND_COMMAND(tr);
+ cmd->generic.host_id = sc->twe_host_id; /* controller-assigned host ID */
+ cmd->generic.request_id = i; /* our index number */
sc->twe_lookup[i] = tr;
/*
@@ -369,6 +370,9 @@ twe_startio(struct twe_softc *sc)
debug_called(4);
+ if (sc->twe_state & TWE_STATE_FRZN)
+ return;
+
/* spin until something prevents us from doing any work */
for (;;) {
@@ -393,7 +397,7 @@ twe_startio(struct twe_softc *sc)
tr->tr_private = bp;
tr->tr_data = TWE_BIO_DATA(bp);
tr->tr_length = TWE_BIO_LENGTH(bp);
- cmd = &tr->tr_command;
+ cmd = TWE_FIND_COMMAND(tr);
if (TWE_BIO_IS_READ(bp)) {
tr->tr_flags |= TWE_CMD_DATAIN;
cmd->io.opcode = TWE_OP_READ;
@@ -407,25 +411,22 @@ twe_startio(struct twe_softc *sc)
cmd->io.unit = TWE_BIO_UNIT(bp);
cmd->io.block_count = (tr->tr_length + TWE_BLOCK_SIZE - 1) / TWE_BLOCK_SIZE;
cmd->io.lba = TWE_BIO_LBA(bp);
-
- /* map the command so the controller can work with it */
- twe_map_request(tr);
}
/* did we find something to do? */
if (tr == NULL)
break;
- /* try to give command to controller */
- error = twe_start(tr);
-
+ /* map the command so the controller can work with it */
+ error = twe_map_request(tr);
if (error != 0) {
if (error == EBUSY) {
twe_requeue_ready(tr); /* try it again later */
break; /* don't try anything more for now */
}
+
/* we don't support any other return from twe_start */
- twe_panic(sc, "twe_start returned nonsense");
+ twe_panic(sc, "twe_map_request returned nonsense");
}
}
}
@@ -448,14 +449,13 @@ twe_dump_blocks(struct twe_softc *sc, int unit, u_int32_t lba, void *data, int n
tr->tr_length = nblks * TWE_BLOCK_SIZE;
tr->tr_flags = TWE_CMD_DATAOUT;
- cmd = &tr->tr_command;
+ cmd = TWE_FIND_COMMAND(tr);
cmd->io.opcode = TWE_OP_WRITE;
cmd->io.size = 3;
cmd->io.unit = unit;
cmd->io.block_count = nblks;
cmd->io.lba = lba;
- twe_map_request(tr);
error = twe_immediate_request(tr);
if (error == 0)
if (twe_report_request(tr))
@@ -468,13 +468,14 @@ twe_dump_blocks(struct twe_softc *sc, int unit, u_int32_t lba, void *data, int n
* Handle controller-specific control operations.
*/
int
-twe_ioctl(struct twe_softc *sc, int cmd, void *addr)
+twe_ioctl(struct twe_softc *sc, int ioctlcmd, 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;
+ TWE_Command *cmd;
void *data;
int *arg = (int *)addr;
struct twe_request *tr;
@@ -482,7 +483,7 @@ twe_ioctl(struct twe_softc *sc, int cmd, void *addr)
int s, error;
error = 0;
- switch(cmd) {
+ switch(ioctlcmd) {
/* handle a command from userspace */
case TWEIO_COMMAND:
/* get a request */
@@ -493,9 +494,10 @@ twe_ioctl(struct twe_softc *sc, int cmd, void *addr)
* Save the command's request ID, copy the user-supplied command in,
* restore the request ID.
*/
- srid = tr->tr_command.generic.request_id;
- bcopy(&tu->tu_command, &tr->tr_command, sizeof(TWE_Command));
- tr->tr_command.generic.request_id = srid;
+ cmd = TWE_FIND_COMMAND(tr);
+ srid = cmd->generic.request_id;
+ bcopy(&tu->tu_command, cmd, sizeof(TWE_Command));
+ cmd->generic.request_id = srid;
/*
* if there's a data buffer, allocate and copy it in.
@@ -513,11 +515,10 @@ twe_ioctl(struct twe_softc *sc, int cmd, void *addr)
}
/* run the command */
- twe_map_request(tr);
twe_wait_request(tr);
/* copy the command out again */
- bcopy(&tr->tr_command, &tu->tu_command, sizeof(TWE_Command));
+ bcopy(cmd, &tu->tu_command, sizeof(TWE_Command));
/* if there was a data buffer, copy it out */
if (tr->tr_length > 0)
@@ -716,15 +717,12 @@ twe_get_param(struct twe_softc *sc, int table_id, int param_id, size_t param_siz
tr->tr_flags = TWE_CMD_DATAIN | TWE_CMD_DATAOUT;
/* build the command for the controller */
- cmd = &tr->tr_command;
+ cmd = TWE_FIND_COMMAND(tr);
cmd->param.opcode = TWE_OP_GET_PARAM;
cmd->param.size = 2;
cmd->param.unit = 0;
cmd->param.param_count = 1;
- /* map the command/data into controller-visible space */
- twe_map_request(tr);
-
/* fill in the outbound parameter data */
param->table_id = table_id;
param->parameter_id = param_id;
@@ -742,7 +740,7 @@ twe_get_param(struct twe_softc *sc, int table_id, int param_id, size_t param_siz
return(param);
} else {
tr->tr_complete = func;
- error = twe_start(tr);
+ error = twe_map_request(tr);
if (error == 0)
return(func);
}
@@ -811,15 +809,12 @@ twe_set_param(struct twe_softc *sc, int table_id, int param_id, int param_size,
tr->tr_flags = TWE_CMD_DATAIN | TWE_CMD_DATAOUT;
/* build the command for the controller */
- cmd = &tr->tr_command;
+ cmd = TWE_FIND_COMMAND(tr);
cmd->param.opcode = TWE_OP_SET_PARAM;
cmd->param.size = 2;
cmd->param.unit = 0;
cmd->param.param_count = 1;
- /* map the command/data into controller-visible space */
- twe_map_request(tr);
-
/* fill in the outbound parameter data */
param->table_id = table_id;
param->parameter_id = param_id;
@@ -860,16 +855,13 @@ twe_init_connection(struct twe_softc *sc, int mode)
return(0);
/* build the command */
- cmd = &tr->tr_command;
+ cmd = TWE_FIND_COMMAND(tr);
cmd->initconnection.opcode = TWE_OP_INIT_CONNECTION;
cmd->initconnection.size = 3;
cmd->initconnection.host_id = 0;
cmd->initconnection.message_credits = mode;
cmd->initconnection.response_queue_pointer = 0;
- /* map the command into controller-visible space */
- twe_map_request(tr);
-
/* submit the command */
error = twe_immediate_request(tr);
/* XXX check command result? */
@@ -913,14 +905,13 @@ twe_wait_request(struct twe_request *tr)
static int
twe_immediate_request(struct twe_request *tr)
{
- int error;
debug_called(4);
- error = 0;
+ tr->tr_flags |= TWE_CMD_IMMEDIATE;
+ tr->tr_status = TWE_CMD_BUSY;
+ twe_map_request(tr);
- if ((error = twe_start(tr)) != 0)
- return(error);
while (tr->tr_status == TWE_CMD_BUSY){
twe_done(tr->tr_sc);
}
@@ -1023,10 +1014,11 @@ out:
*
* Can be called at any interrupt level, with or without interrupts enabled.
*/
-static int
+int
twe_start(struct twe_request *tr)
{
struct twe_softc *sc = tr->tr_sc;
+ TWE_Command *cmd;
int i, s, done;
u_int32_t status_reg;
@@ -1034,6 +1026,7 @@ twe_start(struct twe_request *tr)
/* mark the command as currently being processed */
tr->tr_status = TWE_CMD_BUSY;
+ cmd = TWE_FIND_COMMAND(tr);
/*
* Spin briefly waiting for the controller to come ready
@@ -1049,17 +1042,18 @@ twe_start(struct twe_request *tr)
twe_check_bits(sc, status_reg);
if (!(status_reg & TWE_STATUS_COMMAND_QUEUE_FULL)) {
- TWE_COMMAND_QUEUE(sc, tr->tr_cmdphys);
+ twe_enqueue_busy(tr);
+
+ TWE_COMMAND_QUEUE(sc, TWE_FIND_COMMANDPHYS(tr));
done = 1;
/* move command to work queue */
- twe_enqueue_busy(tr);
#ifdef TWE_DEBUG
if (tr->tr_complete != NULL) {
- debug(3, "queued request %d with callback %p", tr->tr_command.generic.request_id, tr->tr_complete);
+ debug(3, "queued request %d with callback %p", cmd->generic.request_id, tr->tr_complete);
} else if (tr->tr_flags & TWE_CMD_SLEEPER) {
- debug(3, "queued request %d with wait channel %p", tr->tr_command.generic.request_id, tr);
+ debug(3, "queued request %d with wait channel %p", cmd->generic.request_id, tr);
} else {
- debug(3, "queued request %d for polling caller", tr->tr_command.generic.request_id);
+ debug(3, "queued request %d for polling caller", cmd->generic.request_id);
}
#endif
}
@@ -1088,6 +1082,7 @@ static void
twe_done(struct twe_softc *sc)
{
TWE_Response_Queue rq;
+ TWE_Command *cmd;
struct twe_request *tr;
int s, found;
u_int32_t status_reg;
@@ -1105,11 +1100,12 @@ twe_done(struct twe_softc *sc)
found = 1;
rq = TWE_RESPONSE_QUEUE(sc);
tr = sc->twe_lookup[rq.u.response_id]; /* find command */
+ cmd = TWE_FIND_COMMAND(tr);
if (tr->tr_status != TWE_CMD_BUSY)
twe_printf(sc, "completion event for nonbusy command\n");
tr->tr_status = TWE_CMD_COMPLETE;
debug(3, "completed request id %d with status %d",
- tr->tr_command.generic.request_id, tr->tr_command.generic.status);
+ cmd->generic.request_id, cmd->generic.status);
/* move to completed queue */
twe_remove_busy(tr);
twe_enqueue_complete(tr);
@@ -1144,7 +1140,6 @@ twe_complete(struct twe_softc *sc)
* Pull commands off the completed list, dispatch them appropriately
*/
while ((tr = twe_dequeue_complete(sc)) != NULL) {
-
/* unmap the command's data buffer */
twe_unmap_request(tr);
@@ -1161,6 +1156,8 @@ twe_complete(struct twe_softc *sc)
debug(2, "command left for owner");
}
}
+
+ sc->twe_state &= ~TWE_STATE_FRZN;
}
/********************************************************************************
@@ -1502,6 +1499,7 @@ twe_wait_aen(struct twe_softc *sc, int aen, int timeout)
static int
twe_get_request(struct twe_softc *sc, struct twe_request **tr)
{
+ TWE_Command *cmd;
debug_called(4);
/* try to reuse an old buffer */
@@ -1509,13 +1507,14 @@ twe_get_request(struct twe_softc *sc, struct twe_request **tr)
/* initialise some fields to their defaults */
if (*tr != NULL) {
+ cmd = TWE_FIND_COMMAND(*tr);
(*tr)->tr_data = NULL;
(*tr)->tr_private = NULL;
(*tr)->tr_status = TWE_CMD_SETUP; /* command is in setup phase */
(*tr)->tr_flags = 0;
(*tr)->tr_complete = NULL;
- (*tr)->tr_command.generic.status = 0; /* before submission to controller */
- (*tr)->tr_command.generic.flags = 0; /* not used */
+ cmd->generic.status = 0; /* before submission to controller */
+ cmd->generic.flags = 0; /* not used */
}
return(*tr == NULL);
}
@@ -1638,7 +1637,7 @@ twe_check_bits(struct twe_softc *sc, u_int32_t status_reg)
twe_clear_pci_parity_error(sc);
}
if (status_reg & TWE_STATUS_PCI_ABORT) {
- twe_printf(sc, "PCI abort, clearing.");
+ twe_printf(sc, "PCI abort, clearing.\n");
twe_clear_pci_abort(sc);
}
}
@@ -1705,7 +1704,7 @@ static int
twe_report_request(struct twe_request *tr)
{
struct twe_softc *sc = tr->tr_sc;
- TWE_Command *cmd = &tr->tr_command;
+ TWE_Command *cmd = TWE_FIND_COMMAND(tr);
int result = 0;
/*
@@ -1791,7 +1790,7 @@ twe_panic(struct twe_softc *sc, char *reason)
#endif
}
-#if 0
+#ifdef TWE_DEBUG
/********************************************************************************
* Print a request/command in human-readable format.
*/
@@ -1799,7 +1798,7 @@ static void
twe_print_request(struct twe_request *tr)
{
struct twe_softc *sc = tr->tr_sc;
- TWE_Command *cmd = &tr->tr_command;
+ TWE_Command *cmd = TWE_FIND_COMMAND(tr);
int i;
twe_printf(sc, "CMD: request_id %d opcode <%s> size %d unit %d host_id %d\n",
@@ -1833,7 +1832,7 @@ twe_print_request(struct twe_request *tr)
break;
}
twe_printf(sc, " tr_command %p/0x%x tr_data %p/0x%x,%d\n",
- tr, tr->tr_cmdphys, tr->tr_data, tr->tr_dataphys, tr->tr_length);
+ tr, TWE_FIND_COMMANDPHYS(tr), tr->tr_data, tr->tr_dataphys, tr->tr_length);
twe_printf(sc, " tr_status %d tr_flags 0x%x tr_complete %p tr_private %p\n",
tr->tr_status, tr->tr_flags, tr->tr_complete, tr->tr_private);
}
OpenPOWER on IntegriCloud