diff options
Diffstat (limited to 'drivers/scsi/esp_scsi.c')
-rw-r--r-- | drivers/scsi/esp_scsi.c | 428 |
1 files changed, 247 insertions, 181 deletions
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c index 55548dc5cec3..ce5bd52fe692 100644 --- a/drivers/scsi/esp_scsi.c +++ b/drivers/scsi/esp_scsi.c @@ -49,55 +49,67 @@ static u32 esp_debug; #define ESP_DEBUG_DATADONE 0x00000100 #define ESP_DEBUG_RECONNECT 0x00000200 #define ESP_DEBUG_AUTOSENSE 0x00000400 +#define ESP_DEBUG_EVENT 0x00000800 +#define ESP_DEBUG_COMMAND 0x00001000 #define esp_log_intr(f, a...) \ do { if (esp_debug & ESP_DEBUG_INTR) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_reset(f, a...) \ do { if (esp_debug & ESP_DEBUG_RESET) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_msgin(f, a...) \ do { if (esp_debug & ESP_DEBUG_MSGIN) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_msgout(f, a...) \ do { if (esp_debug & ESP_DEBUG_MSGOUT) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_cmddone(f, a...) \ do { if (esp_debug & ESP_DEBUG_CMDDONE) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_disconnect(f, a...) \ do { if (esp_debug & ESP_DEBUG_DISCONNECT) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_datastart(f, a...) \ do { if (esp_debug & ESP_DEBUG_DATASTART) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_datadone(f, a...) \ do { if (esp_debug & ESP_DEBUG_DATADONE) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_reconnect(f, a...) \ do { if (esp_debug & ESP_DEBUG_RECONNECT) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_autosense(f, a...) \ do { if (esp_debug & ESP_DEBUG_AUTOSENSE) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ +} while (0) + +#define esp_log_event(f, a...) \ +do { if (esp_debug & ESP_DEBUG_EVENT) \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ +} while (0) + +#define esp_log_command(f, a...) \ +do { if (esp_debug & ESP_DEBUG_COMMAND) \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_read8(REG) esp->ops->esp_read8(esp, REG) @@ -126,10 +138,29 @@ void scsi_esp_cmd(struct esp *esp, u8 val) esp->esp_event_cur = (idx + 1) & (ESP_EVENT_LOG_SZ - 1); + esp_log_command("cmd[%02x]\n", val); esp_write8(val, ESP_CMD); } EXPORT_SYMBOL(scsi_esp_cmd); +static void esp_send_dma_cmd(struct esp *esp, int len, int max_len, int cmd) +{ + if (esp->flags & ESP_FLAG_USE_FIFO) { + int i; + + scsi_esp_cmd(esp, ESP_CMD_FLUSH); + for (i = 0; i < len; i++) + esp_write8(esp->command_block[i], ESP_FDATA); + scsi_esp_cmd(esp, cmd); + } else { + if (esp->rev == FASHME) + scsi_esp_cmd(esp, ESP_CMD_FLUSH); + cmd |= ESP_CMD_DMA; + esp->ops->send_dma_cmd(esp, esp->command_block_dma, + len, max_len, 0, cmd); + } +} + static void esp_event(struct esp *esp, u8 val) { struct esp_event_ent *p; @@ -150,19 +181,17 @@ static void esp_dump_cmd_log(struct esp *esp) int idx = esp->esp_event_cur; int stop = idx; - printk(KERN_INFO PFX "esp%d: Dumping command log\n", - esp->host->unique_id); + shost_printk(KERN_INFO, esp->host, "Dumping command log\n"); do { struct esp_event_ent *p = &esp->esp_event_log[idx]; - printk(KERN_INFO PFX "esp%d: ent[%d] %s ", - esp->host->unique_id, idx, - p->type == ESP_EVENT_TYPE_CMD ? "CMD" : "EVENT"); - - printk("val[%02x] sreg[%02x] seqreg[%02x] " - "sreg2[%02x] ireg[%02x] ss[%02x] event[%02x]\n", - p->val, p->sreg, p->seqreg, - p->sreg2, p->ireg, p->select_state, p->event); + shost_printk(KERN_INFO, esp->host, + "ent[%d] %s val[%02x] sreg[%02x] seqreg[%02x] " + "sreg2[%02x] ireg[%02x] ss[%02x] event[%02x]\n", + idx, + p->type == ESP_EVENT_TYPE_CMD ? "CMD" : "EVENT", + p->val, p->sreg, p->seqreg, + p->sreg2, p->ireg, p->select_state, p->event); idx = (idx + 1) & (ESP_EVENT_LOG_SZ - 1); } while (idx != stop); @@ -176,9 +205,8 @@ static void esp_flush_fifo(struct esp *esp) while (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES) { if (--lim == 0) { - printk(KERN_ALERT PFX "esp%d: ESP_FF_BYTES " - "will not clear!\n", - esp->host->unique_id); + shost_printk(KERN_ALERT, esp->host, + "ESP_FF_BYTES will not clear!\n"); break; } udelay(1); @@ -240,6 +268,19 @@ static void esp_reset_esp(struct esp *esp) } else { esp->min_period = ((5 * esp->ccycle) / 1000); } + if (esp->rev == FAS236) { + /* + * The AM53c974 chip returns the same ID as FAS236; + * try to configure glitch eater. + */ + u8 config4 = ESP_CONFIG4_GE1; + esp_write8(config4, ESP_CFG4); + config4 = esp_read8(ESP_CFG4); + if (config4 & ESP_CONFIG4_GE1) { + esp->rev = PCSCSI; + esp_write8(esp->config4, ESP_CFG4); + } + } esp->max_period = (esp->max_period + 3)>>2; esp->min_period = (esp->min_period + 3)>>2; @@ -265,7 +306,8 @@ static void esp_reset_esp(struct esp *esp) /* fallthrough... */ case FAS236: - /* Fast 236 or HME */ + case PCSCSI: + /* Fast 236, AM53c974 or HME */ esp_write8(esp->config2, ESP_CFG2); if (esp->rev == FASHME) { u8 cfg3 = esp->target[0].esp_config3; @@ -383,12 +425,11 @@ static void esp_advance_dma(struct esp *esp, struct esp_cmd_entry *ent, p->cur_residue -= len; p->tot_residue -= len; if (p->cur_residue < 0 || p->tot_residue < 0) { - printk(KERN_ERR PFX "esp%d: Data transfer overflow.\n", - esp->host->unique_id); - printk(KERN_ERR PFX "esp%d: cur_residue[%d] tot_residue[%d] " - "len[%u]\n", - esp->host->unique_id, - p->cur_residue, p->tot_residue, len); + shost_printk(KERN_ERR, esp->host, + "Data transfer overflow.\n"); + shost_printk(KERN_ERR, esp->host, + "cur_residue[%d] tot_residue[%d] len[%u]\n", + p->cur_residue, p->tot_residue, len); p->cur_residue = 0; p->tot_residue = 0; } @@ -604,9 +645,8 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent) if (!ent->sense_ptr) { - esp_log_autosense("esp%d: Doing auto-sense for " - "tgt[%d] lun[%d]\n", - esp->host->unique_id, tgt, lun); + esp_log_autosense("Doing auto-sense for tgt[%d] lun[%d]\n", + tgt, lun); ent->sense_ptr = cmd->sense_buffer; ent->sense_dma = esp->ops->map_single(esp, @@ -642,10 +682,7 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent) val = (p - esp->command_block); - if (esp->rev == FASHME) - scsi_esp_cmd(esp, ESP_CMD_FLUSH); - esp->ops->send_dma_cmd(esp, esp->command_block_dma, - val, 16, 0, ESP_CMD_DMA | ESP_CMD_SELA); + esp_send_dma_cmd(esp, val, 16, ESP_CMD_SELA); } static struct esp_cmd_entry *find_and_prep_issuable_command(struct esp *esp) @@ -663,7 +700,7 @@ static struct esp_cmd_entry *find_and_prep_issuable_command(struct esp *esp) return ent; } - if (!scsi_populate_tag_msg(cmd, &ent->tag[0])) { + if (!spi_populate_tag_msg(&ent->tag[0], cmd)) { ent->tag[0] = 0; ent->tag[1] = 0; } @@ -781,12 +818,12 @@ build_identify: } if (!(esp->flags & ESP_FLAG_DOING_SLOWCMD)) { - start_cmd = ESP_CMD_DMA | ESP_CMD_SELA; + start_cmd = ESP_CMD_SELA; if (ent->tag[0]) { *p++ = ent->tag[0]; *p++ = ent->tag[1]; - start_cmd = ESP_CMD_DMA | ESP_CMD_SA3; + start_cmd = ESP_CMD_SA3; } for (i = 0; i < cmd->cmd_len; i++) @@ -806,7 +843,7 @@ build_identify: esp->msg_out_len += 2; } - start_cmd = ESP_CMD_DMA | ESP_CMD_SELAS; + start_cmd = ESP_CMD_SELAS; esp->select_state = ESP_SELECT_MSGOUT; } val = tgt; @@ -826,10 +863,7 @@ build_identify: printk("]\n"); } - if (esp->rev == FASHME) - scsi_esp_cmd(esp, ESP_CMD_FLUSH); - esp->ops->send_dma_cmd(esp, esp->command_block_dma, - val, 16, 0, start_cmd); + esp_send_dma_cmd(esp, val, 16, start_cmd); } static struct esp_cmd_entry *esp_get_ent(struct esp *esp) @@ -953,8 +987,8 @@ static int esp_check_gross_error(struct esp *esp) * - DMA programmed with wrong direction * - improper phase change */ - printk(KERN_ERR PFX "esp%d: Gross error sreg[%02x]\n", - esp->host->unique_id, esp->sreg); + shost_printk(KERN_ERR, esp->host, + "Gross error sreg[%02x]\n", esp->sreg); /* XXX Reset the chip. XXX */ return 1; } @@ -974,7 +1008,6 @@ static int esp_check_spur_intr(struct esp *esp) default: if (!(esp->sreg & ESP_STAT_INTR)) { - esp->ireg = esp_read8(ESP_INTRPT); if (esp->ireg & ESP_INTR_SR) return 1; @@ -982,14 +1015,13 @@ static int esp_check_spur_intr(struct esp *esp) * ESP is not, the only possibility is a DMA error. */ if (!esp->ops->dma_error(esp)) { - printk(KERN_ERR PFX "esp%d: Spurious irq, " - "sreg=%02x.\n", - esp->host->unique_id, esp->sreg); + shost_printk(KERN_ERR, esp->host, + "Spurious irq, sreg=%02x.\n", + esp->sreg); return -1; } - printk(KERN_ERR PFX "esp%d: DMA error\n", - esp->host->unique_id); + shost_printk(KERN_ERR, esp->host, "DMA error\n"); /* XXX Reset the chip. XXX */ return -1; @@ -1002,7 +1034,7 @@ static int esp_check_spur_intr(struct esp *esp) static void esp_schedule_reset(struct esp *esp) { - esp_log_reset("ESP: esp_schedule_reset() from %pf\n", + esp_log_reset("esp_schedule_reset() from %pf\n", __builtin_return_address(0)); esp->flags |= ESP_FLAG_RESETTING; esp_event(esp, ESP_EVENT_RESET); @@ -1019,20 +1051,20 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp, int i; if (!lp->num_tagged) { - printk(KERN_ERR PFX "esp%d: Reconnect w/num_tagged==0\n", - esp->host->unique_id); + shost_printk(KERN_ERR, esp->host, + "Reconnect w/num_tagged==0\n"); return NULL; } - esp_log_reconnect("ESP: reconnect tag, "); + esp_log_reconnect("reconnect tag, "); for (i = 0; i < ESP_QUICKIRQ_LIMIT; i++) { if (esp->ops->irq_pending(esp)) break; } if (i == ESP_QUICKIRQ_LIMIT) { - printk(KERN_ERR PFX "esp%d: Reconnect IRQ1 timeout\n", - esp->host->unique_id); + shost_printk(KERN_ERR, esp->host, + "Reconnect IRQ1 timeout\n"); return NULL; } @@ -1043,14 +1075,14 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp, i, esp->ireg, esp->sreg); if (esp->ireg & ESP_INTR_DC) { - printk(KERN_ERR PFX "esp%d: Reconnect, got disconnect.\n", - esp->host->unique_id); + shost_printk(KERN_ERR, esp->host, + "Reconnect, got disconnect.\n"); return NULL; } if ((esp->sreg & ESP_STAT_PMASK) != ESP_MIP) { - printk(KERN_ERR PFX "esp%d: Reconnect, not MIP sreg[%02x].\n", - esp->host->unique_id, esp->sreg); + shost_printk(KERN_ERR, esp->host, + "Reconnect, not MIP sreg[%02x].\n", esp->sreg); return NULL; } @@ -1073,8 +1105,7 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp, udelay(1); } if (i == ESP_RESELECT_TAG_LIMIT) { - printk(KERN_ERR PFX "esp%d: Reconnect IRQ2 timeout\n", - esp->host->unique_id); + shost_printk(KERN_ERR, esp->host, "Reconnect IRQ2 timeout\n"); return NULL; } esp->ops->dma_drain(esp); @@ -1087,17 +1118,17 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp, if (esp->command_block[0] < SIMPLE_QUEUE_TAG || esp->command_block[0] > ORDERED_QUEUE_TAG) { - printk(KERN_ERR PFX "esp%d: Reconnect, bad tag " - "type %02x.\n", - esp->host->unique_id, esp->command_block[0]); + shost_printk(KERN_ERR, esp->host, + "Reconnect, bad tag type %02x.\n", + esp->command_block[0]); return NULL; } ent = lp->tagged_cmds[esp->command_block[1]]; if (!ent) { - printk(KERN_ERR PFX "esp%d: Reconnect, no entry for " - "tag %02x.\n", - esp->host->unique_id, esp->command_block[1]); + shost_printk(KERN_ERR, esp->host, + "Reconnect, no entry for tag %02x.\n", + esp->command_block[1]); return NULL; } @@ -1163,9 +1194,9 @@ static int esp_reconnect(struct esp *esp) tp = &esp->target[target]; dev = __scsi_device_lookup_by_target(tp->starget, lun); if (!dev) { - printk(KERN_ERR PFX "esp%d: Reconnect, no lp " - "tgt[%u] lun[%u]\n", - esp->host->unique_id, target, lun); + shost_printk(KERN_ERR, esp->host, + "Reconnect, no lp tgt[%u] lun[%u]\n", + target, lun); goto do_reset; } lp = dev->hostdata; @@ -1291,8 +1322,8 @@ static int esp_finish_select(struct esp *esp) return 0; } - printk("ESP: Unexpected selection completion ireg[%x].\n", - esp->ireg); + shost_printk(KERN_INFO, esp->host, + "Unexpected selection completion ireg[%x]\n", esp->ireg); esp_schedule_reset(esp); return 0; } @@ -1312,11 +1343,42 @@ static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent, (((unsigned int)esp_read8(ESP_TCMED)) << 8)); if (esp->rev == FASHME) ecount |= ((unsigned int)esp_read8(FAS_RLO)) << 16; + if (esp->rev == PCSCSI && (esp->config2 & ESP_CONFIG2_FENAB)) + ecount |= ((unsigned int)esp_read8(ESP_TCHI)) << 16; } bytes_sent = esp->data_dma_len; bytes_sent -= ecount; + /* + * The am53c974 has a DMA 'pecularity'. The doc states: + * In some odd byte conditions, one residual byte will + * be left in the SCSI FIFO, and the FIFO Flags will + * never count to '0 '. When this happens, the residual + * byte should be retrieved via PIO following completion + * of the BLAST operation. + */ + if (fifo_cnt == 1 && ent->flags & ESP_CMD_FLAG_RESIDUAL) { + size_t count = 1; + size_t offset = bytes_sent; + u8 bval = esp_read8(ESP_FDATA); + + if (ent->flags & ESP_CMD_FLAG_AUTOSENSE) + ent->sense_ptr[bytes_sent] = bval; + else { + struct esp_cmd_priv *p = ESP_CMD_PRIV(cmd); + u8 *ptr; + + ptr = scsi_kmap_atomic_sg(p->cur_sg, p->u.num_sg, + &offset, &count); + if (likely(ptr)) { + *(ptr + offset) = bval; + scsi_kunmap_atomic_sg(ptr); + } + } + bytes_sent += fifo_cnt; + ent->flags &= ~ESP_CMD_FLAG_RESIDUAL; + } if (!(ent->flags & ESP_CMD_FLAG_WRITE)) bytes_sent -= fifo_cnt; @@ -1556,8 +1618,8 @@ static void esp_msgin_extended(struct esp *esp) return; } - printk("ESP: Unexpected extended msg type %x\n", - esp->msg_in[2]); + shost_printk(KERN_INFO, esp->host, + "Unexpected extended msg type %x\n", esp->msg_in[2]); esp->msg_out[0] = ABORT_TASK_SET; esp->msg_out_len = 1; @@ -1574,7 +1636,8 @@ static int esp_msgin_process(struct esp *esp) if (msg0 & 0x80) { /* Identify */ - printk("ESP: Unexpected msgin identify\n"); + shost_printk(KERN_INFO, esp->host, + "Unexpected msgin identify\n"); return 0; } @@ -1640,10 +1703,12 @@ static int esp_msgin_process(struct esp *esp) static int esp_process_event(struct esp *esp) { - int write; + int write, i; again: write = 0; + esp_log_event("process event %d phase %x\n", + esp->event, esp->sreg & ESP_STAT_PMASK); switch (esp->event) { case ESP_EVENT_CHECK_PHASE: switch (esp->sreg & ESP_STAT_PMASK) { @@ -1673,8 +1738,9 @@ again: break; default: - printk("ESP: Unexpected phase, sreg=%02x\n", - esp->sreg); + shost_printk(KERN_INFO, esp->host, + "Unexpected phase, sreg=%02x\n", + esp->sreg); esp_schedule_reset(esp); return 0; } @@ -1708,18 +1774,17 @@ again: esp->data_dma_len = dma_len; if (!dma_len) { - printk(KERN_ERR PFX "esp%d: DMA length is zero!\n", - esp->host->unique_id); - printk(KERN_ERR PFX "esp%d: cur adr[%08llx] len[%08x]\n", - esp->host->unique_id, - (unsigned long long)esp_cur_dma_addr(ent, cmd), - esp_cur_dma_len(ent, cmd)); + shost_printk(KERN_ERR, esp->host, + "DMA length is zero!\n"); + shost_printk(KERN_ERR, esp->host, + "cur adr[%08llx] len[%08x]\n", + (unsigned long long)esp_cur_dma_addr(ent, cmd), + esp_cur_dma_len(ent, cmd)); esp_schedule_reset(esp); return 0; } - esp_log_datastart("ESP: start data addr[%08llx] len[%u] " - "write(%d)\n", + esp_log_datastart("start data addr[%08llx] len[%u] write(%d)\n", (unsigned long long)dma_addr, dma_len, write); esp->ops->send_dma_cmd(esp, dma_addr, dma_len, dma_len, @@ -1733,7 +1798,8 @@ again: int bytes_sent; if (esp->ops->dma_error(esp)) { - printk("ESP: data done, DMA error, resetting\n"); + shost_printk(KERN_INFO, esp->host, + "data done, DMA error, resetting\n"); esp_schedule_reset(esp); return 0; } @@ -1749,14 +1815,15 @@ again: /* We should always see exactly a bus-service * interrupt at the end of a successful transfer. */ - printk("ESP: data done, not BSERV, resetting\n"); + shost_printk(KERN_INFO, esp->host, + "data done, not BSERV, resetting\n"); esp_schedule_reset(esp); return 0; } bytes_sent = esp_data_bytes_sent(esp, ent, cmd); - esp_log_datadone("ESP: data done flgs[%x] sent[%d]\n", + esp_log_datadone("data done flgs[%x] sent[%d]\n", ent->flags, bytes_sent); if (bytes_sent < 0) { @@ -1785,8 +1852,9 @@ again: } if (ent->message != COMMAND_COMPLETE) { - printk("ESP: Unexpected message %x in status\n", - ent->message); + shost_printk(KERN_INFO, esp->host, + "Unexpected message %x in status\n", + ent->message); esp_schedule_reset(esp); return 0; } @@ -1804,8 +1872,7 @@ again: scsi_esp_cmd(esp, ESP_CMD_ESEL); if (ent->message == COMMAND_COMPLETE) { - esp_log_cmddone("ESP: Command done status[%x] " - "message[%x]\n", + esp_log_cmddone("Command done status[%x] message[%x]\n", ent->status, ent->message); if (ent->status == SAM_STAT_TASK_SET_FULL) esp_event_queue_full(esp, ent); @@ -1821,16 +1888,16 @@ again: DID_OK)); } } else if (ent->message == DISCONNECT) { - esp_log_disconnect("ESP: Disconnecting tgt[%d] " - "tag[%x:%x]\n", + esp_log_disconnect("Disconnecting tgt[%d] tag[%x:%x]\n", cmd->device->id, ent->tag[0], ent->tag[1]); esp->active_cmd = NULL; esp_maybe_execute_command(esp); } else { - printk("ESP: Unexpected message %x in freebus\n", - ent->message); + shost_printk(KERN_INFO, esp->host, + "Unexpected message %x in freebus\n", + ent->message); esp_schedule_reset(esp); return 0; } @@ -1862,6 +1929,10 @@ again: if (esp->msg_out_len == 1) { esp_write8(esp->msg_out[0], ESP_FDATA); scsi_esp_cmd(esp, ESP_CMD_TI); + } else if (esp->flags & ESP_FLAG_USE_FIFO) { + for (i = 0; i < esp->msg_out_len; i++) + esp_write8(esp->msg_out[i], ESP_FDATA); + scsi_esp_cmd(esp, ESP_CMD_TI); } else { /* Use DMA. */ memcpy(esp->command_block, @@ -1917,7 +1988,7 @@ again: val = esp_read8(ESP_FDATA); esp->msg_in[esp->msg_in_len++] = val; - esp_log_msgin("ESP: Got msgin byte %x\n", val); + esp_log_msgin("Got msgin byte %x\n", val); if (!esp_msgin_process(esp)) esp->msg_in_len = 0; @@ -1930,7 +2001,8 @@ again: if (esp->event != ESP_EVENT_FREE_BUS) esp_event(esp, ESP_EVENT_CHECK_PHASE); } else { - printk("ESP: MSGIN neither BSERV not FDON, resetting"); + shost_printk(KERN_INFO, esp->host, + "MSGIN neither BSERV not FDON, resetting"); esp_schedule_reset(esp); return 0; } @@ -1938,11 +2010,7 @@ again: case ESP_EVENT_CMD_START: memcpy(esp->command_block, esp->cmd_bytes_ptr, esp->cmd_bytes_left); - if (esp->rev == FASHME) - scsi_esp_cmd(esp, ESP_CMD_FLUSH); - esp->ops->send_dma_cmd(esp, esp->command_block_dma, - esp->cmd_bytes_left, 16, 0, - ESP_CMD_DMA | ESP_CMD_TI); + esp_send_dma_cmd(esp, esp->cmd_bytes_left, 16, ESP_CMD_TI); esp_event(esp, ESP_EVENT_CMD_DONE); esp->flags |= ESP_FLAG_QUICKIRQ_CHECK; break; @@ -1961,8 +2029,8 @@ again: break; default: - printk("ESP: Unexpected event %x, resetting\n", - esp->event); + shost_printk(KERN_INFO, esp->host, + "Unexpected event %x, resetting\n", esp->event); esp_schedule_reset(esp); return 0; break; @@ -2044,7 +2112,12 @@ static void __esp_interrupt(struct esp *esp) int finish_reset, intr_done; u8 phase; + /* + * Once INTRPT is read STATUS and SSTEP are cleared. + */ esp->sreg = esp_read8(ESP_STATUS); + esp->seqreg = esp_read8(ESP_SSTEP); + esp->ireg = esp_read8(ESP_INTRPT); if (esp->flags & ESP_FLAG_RESETTING) { finish_reset = 1; @@ -2057,8 +2130,6 @@ static void __esp_interrupt(struct esp *esp) return; } - esp->ireg = esp_read8(ESP_INTRPT); - if (esp->ireg & ESP_INTR_SR) finish_reset = 1; @@ -2085,14 +2156,15 @@ static void __esp_interrupt(struct esp *esp) } } - esp_log_intr("ESP: intr sreg[%02x] seqreg[%02x] " + esp_log_intr("intr sreg[%02x] seqreg[%02x] " "sreg2[%02x] ireg[%02x]\n", esp->sreg, esp->seqreg, esp->sreg2, esp->ireg); intr_done = 0; if (esp->ireg & (ESP_INTR_S | ESP_INTR_SATN | ESP_INTR_IC)) { - printk("ESP: unexpected IREG %02x\n", esp->ireg); + shost_printk(KERN_INFO, esp->host, + "unexpected IREG %02x\n", esp->ireg); if (esp->ireg & ESP_INTR_IC) esp_dump_cmd_log(esp); @@ -2149,46 +2221,50 @@ static void esp_get_revision(struct esp *esp) u8 val; esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7)); - esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY); + if (esp->config2 == 0) { + esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY); + esp_write8(esp->config2, ESP_CFG2); + + val = esp_read8(ESP_CFG2); + val &= ~ESP_CONFIG2_MAGIC; + + esp->config2 = 0; + if (val != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) { + /* + * If what we write to cfg2 does not come back, + * cfg2 is not implemented. + * Therefore this must be a plain esp100. + */ + esp->rev = ESP100; + return; + } + } + + esp_set_all_config3(esp, 5); + esp->prev_cfg3 = 5; esp_write8(esp->config2, ESP_CFG2); + esp_write8(0, ESP_CFG3); + esp_write8(esp->prev_cfg3, ESP_CFG3); - val = esp_read8(ESP_CFG2); - val &= ~ESP_CONFIG2_MAGIC; - if (val != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) { - /* If what we write to cfg2 does not come back, cfg2 is not - * implemented, therefore this must be a plain esp100. + val = esp_read8(ESP_CFG3); + if (val != 5) { + /* The cfg2 register is implemented, however + * cfg3 is not, must be esp100a. */ - esp->rev = ESP100; + esp->rev = ESP100A; } else { - esp->config2 = 0; - esp_set_all_config3(esp, 5); - esp->prev_cfg3 = 5; - esp_write8(esp->config2, ESP_CFG2); - esp_write8(0, ESP_CFG3); + esp_set_all_config3(esp, 0); + esp->prev_cfg3 = 0; esp_write8(esp->prev_cfg3, ESP_CFG3); - val = esp_read8(ESP_CFG3); - if (val != 5) { - /* The cfg2 register is implemented, however - * cfg3 is not, must be esp100a. - */ - esp->rev = ESP100A; + /* All of cfg{1,2,3} implemented, must be one of + * the fas variants, figure out which one. + */ + if (esp->cfact == 0 || esp->cfact > ESP_CCF_F5) { + esp->rev = FAST; + esp->sync_defp = SYNC_DEFP_FAST; } else { - esp_set_all_config3(esp, 0); - esp->prev_cfg3 = 0; - esp_write8(esp->prev_cfg3, ESP_CFG3); - - /* All of cfg{1,2,3} implemented, must be one of - * the fas variants, figure out which one. - */ - if (esp->cfact == 0 || esp->cfact > ESP_CCF_F5) { - esp->rev = FAST; - esp->sync_defp = SYNC_DEFP_FAST; - } else { - esp->rev = ESP236; - } - esp->config2 = 0; - esp_write8(esp->config2, ESP_CFG2); + esp->rev = ESP236; } } } @@ -2308,6 +2384,7 @@ static const char *esp_chip_names[] = { "FAS100A", "FAST", "FASHME", + "AM53C974", }; static struct scsi_transport_template *esp_transport_template; @@ -2317,6 +2394,10 @@ int scsi_esp_register(struct esp *esp, struct device *dev) static int instance; int err; + if (!esp->num_tags) + esp->num_tags = ESP_DEFAULT_TAGS; + else if (esp->num_tags >= ESP_MAX_TAG) + esp->num_tags = ESP_MAX_TAG - 1; esp->host->transportt = esp_transport_template; esp->host->max_lun = ESP_MAX_LUN; esp->host->cmd_per_lun = 2; @@ -2330,12 +2411,13 @@ int scsi_esp_register(struct esp *esp, struct device *dev) esp_bootup_reset(esp); - printk(KERN_INFO PFX "esp%u, regs[%1p:%1p] irq[%u]\n", - esp->host->unique_id, esp->regs, esp->dma_regs, - esp->host->irq); - printk(KERN_INFO PFX "esp%u is a %s, %u MHz (ccf=%u), SCSI ID %u\n", - esp->host->unique_id, esp_chip_names[esp->rev], - esp->cfreq / 1000000, esp->cfact, esp->scsi_id); + dev_printk(KERN_INFO, dev, "esp%u: regs[%1p:%1p] irq[%u]\n", + esp->host->unique_id, esp->regs, esp->dma_regs, + esp->host->irq); + dev_printk(KERN_INFO, dev, + "esp%u: is a %s, %u MHz (ccf=%u), SCSI ID %u\n", + esp->host->unique_id, esp_chip_names[esp->rev], + esp->cfreq / 1000000, esp->cfact, esp->scsi_id); /* Let the SCSI bus reset settle. */ ssleep(esp_bus_reset_settle); @@ -2402,28 +2484,10 @@ static int esp_slave_configure(struct scsi_device *dev) { struct esp *esp = shost_priv(dev->host); struct esp_target_data *tp = &esp->target[dev->id]; - int goal_tags, queue_depth; - - goal_tags = 0; - if (dev->tagged_supported) { - /* XXX make this configurable somehow XXX */ - goal_tags = ESP_DEFAULT_TAGS; - - if (goal_tags > ESP_MAX_TAG) - goal_tags = ESP_MAX_TAG; - } + if (dev->tagged_supported) + scsi_change_queue_depth(dev, esp->num_tags); - queue_depth = goal_tags; - if (queue_depth < dev->host->cmd_per_lun) - queue_depth = dev->host->cmd_per_lun; - - if (goal_tags) { - scsi_set_tag_type(dev, MSG_ORDERED_TAG); - scsi_activate_tcq(dev, queue_depth); - } else { - scsi_deactivate_tcq(dev, queue_depth); - } tp->flags |= ESP_TGT_DISCONNECT; if (!spi_initial_dv(dev->sdev_target)) @@ -2451,19 +2515,20 @@ static int esp_eh_abort_handler(struct scsi_cmnd *cmd) * XXX much for the final driver. */ spin_lock_irqsave(esp->host->host_lock, flags); - printk(KERN_ERR PFX "esp%d: Aborting command [%p:%02x]\n", - esp->host->unique_id, cmd, cmd->cmnd[0]); + shost_printk(KERN_ERR, esp->host, "Aborting command [%p:%02x]\n", + cmd, cmd->cmnd[0]); ent = esp->active_cmd; if (ent) - printk(KERN_ERR PFX "esp%d: Current command [%p:%02x]\n", - esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]); + shost_printk(KERN_ERR, esp->host, + "Current command [%p:%02x]\n", + ent->cmd, ent->cmd->cmnd[0]); list_for_each_entry(ent, &esp->queued_cmds, list) { - printk(KERN_ERR PFX "esp%d: Queued command [%p:%02x]\n", - esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]); + shost_printk(KERN_ERR, esp->host, "Queued command [%p:%02x]\n", + ent->cmd, ent->cmd->cmnd[0]); } list_for_each_entry(ent, &esp->active_cmds, list) { - printk(KERN_ERR PFX "esp%d: Active command [%p:%02x]\n", - esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]); + shost_printk(KERN_ERR, esp->host, " Active command [%p:%02x]\n", + ent->cmd, ent->cmd->cmnd[0]); } esp_dump_cmd_log(esp); spin_unlock_irqrestore(esp->host->host_lock, flags); @@ -2631,6 +2696,7 @@ struct scsi_host_template scsi_esp_template = { .use_clustering = ENABLE_CLUSTERING, .max_sectors = 0xffff, .skip_settle_delay = 1, + .use_blk_tags = 1, }; EXPORT_SYMBOL(scsi_esp_template); |