diff options
Diffstat (limited to 'sys/dev/twe/twe.c')
-rw-r--r-- | sys/dev/twe/twe.c | 105 |
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); } |