} 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;
/* 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;
(((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;
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;
}
}
}
"FAS100A",
"FAST",
"FASHME",
+ "AM53C974",
};
static struct scsi_transport_template *esp_transport_template;