Commit 53dce332 authored by Finn Thain's avatar Finn Thain Committed by Martin K. Petersen

scsi: esp_scsi: De-duplicate PIO routines

As a temporary measure, the code to implement PIO transfers was
duplicated in zorro_esp and mac_esp. Now that it has stabilized move the
common code into the core driver but don't build it unless needed.

This replaces the inline assembler with more portable writesb() calls.
Optimizing the m68k writesb() implementation is a separate patch.

[mkp: applied by hand]
Signed-off-by: default avatarFinn Thain <fthain@telegraphics.com.au>
Tested-by: default avatarStan Johnson <userm57@yahoo.com>
Tested-by: default avatarMichael Schmitz <schmitzmic@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 8bca2143
......@@ -42,6 +42,9 @@ config SCSI_DMA
bool
default n
config SCSI_ESP_PIO
bool
config SCSI_NETLINK
bool
default n
......@@ -1362,6 +1365,7 @@ config SCSI_ZORRO_ESP
tristate "Zorro ESP SCSI support"
depends on ZORRO && SCSI
select SCSI_SPI_ATTRS
select SCSI_ESP_PIO
help
Support for various NCR53C9x (ESP) based SCSI controllers on Zorro
expansion boards for the Amiga.
......@@ -1404,6 +1408,7 @@ config SCSI_MAC_ESP
tristate "Macintosh NCR53c9[46] SCSI"
depends on MAC && SCSI
select SCSI_SPI_ATTRS
select SCSI_ESP_PIO
help
This is the NCR 53c9x SCSI controller found on most of the 68040
based Macintoshes.
......
......@@ -2782,3 +2782,131 @@ MODULE_PARM_DESC(esp_debug,
module_init(esp_init);
module_exit(esp_exit);
#ifdef CONFIG_SCSI_ESP_PIO
static inline unsigned int esp_wait_for_fifo(struct esp *esp)
{
int i = 500000;
do {
unsigned int fbytes = esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES;
if (fbytes)
return fbytes;
udelay(2);
} while (--i);
shost_printk(KERN_ERR, esp->host, "FIFO is empty. sreg [%02x]\n",
esp_read8(ESP_STATUS));
return 0;
}
static inline int esp_wait_for_intr(struct esp *esp)
{
int i = 500000;
do {
esp->sreg = esp_read8(ESP_STATUS);
if (esp->sreg & ESP_STAT_INTR)
return 0;
udelay(2);
} while (--i);
shost_printk(KERN_ERR, esp->host, "IRQ timeout. sreg [%02x]\n",
esp->sreg);
return 1;
}
#define ESP_FIFO_SIZE 16
void esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
u32 dma_count, int write, u8 cmd)
{
u8 phase = esp->sreg & ESP_STAT_PMASK;
cmd &= ~ESP_CMD_DMA;
esp->send_cmd_error = 0;
if (write) {
u8 *dst = (u8 *)addr;
u8 mask = ~(phase == ESP_MIP ? ESP_INTR_FDONE : ESP_INTR_BSERV);
scsi_esp_cmd(esp, cmd);
while (1) {
if (!esp_wait_for_fifo(esp))
break;
*dst++ = esp_read8(ESP_FDATA);
--esp_count;
if (!esp_count)
break;
if (esp_wait_for_intr(esp)) {
esp->send_cmd_error = 1;
break;
}
if ((esp->sreg & ESP_STAT_PMASK) != phase)
break;
esp->ireg = esp_read8(ESP_INTRPT);
if (esp->ireg & mask) {
esp->send_cmd_error = 1;
break;
}
if (phase == ESP_MIP)
scsi_esp_cmd(esp, ESP_CMD_MOK);
scsi_esp_cmd(esp, ESP_CMD_TI);
}
} else {
unsigned int n = ESP_FIFO_SIZE;
u8 *src = (u8 *)addr;
scsi_esp_cmd(esp, ESP_CMD_FLUSH);
if (n > esp_count)
n = esp_count;
writesb(esp->fifo_reg, src, n);
src += n;
esp_count -= n;
scsi_esp_cmd(esp, cmd);
while (esp_count) {
if (esp_wait_for_intr(esp)) {
esp->send_cmd_error = 1;
break;
}
if ((esp->sreg & ESP_STAT_PMASK) != phase)
break;
esp->ireg = esp_read8(ESP_INTRPT);
if (esp->ireg & ~ESP_INTR_BSERV) {
esp->send_cmd_error = 1;
break;
}
n = ESP_FIFO_SIZE -
(esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES);
if (n > esp_count)
n = esp_count;
writesb(esp->fifo_reg, src, n);
src += n;
esp_count -= n;
scsi_esp_cmd(esp, ESP_CMD_TI);
}
}
esp->send_cmd_residual = esp_count;
}
EXPORT_SYMBOL(esp_send_pio_cmd);
#endif
......@@ -524,6 +524,9 @@ struct esp {
void *dma;
int dmarev;
/* These are used by esp_send_pio_cmd() */
u8 __iomem *fifo_reg;
int send_cmd_error;
u32 send_cmd_residual;
};
......@@ -564,4 +567,7 @@ extern void scsi_esp_unregister(struct esp *);
extern irqreturn_t scsi_esp_intr(int, void *);
extern void scsi_esp_cmd(struct esp *, u8);
extern void esp_send_pio_cmd(struct esp *esp, u32 dma_addr, u32 esp_count,
u32 dma_count, int write, u8 cmd);
#endif /* !(_ESP_SCSI_H) */
......@@ -52,7 +52,6 @@ struct mac_esp_priv {
struct esp *esp;
void __iomem *pdma_regs;
void __iomem *pdma_io;
int error;
};
static struct esp *esp_chips[2];
static DEFINE_SPINLOCK(esp_chips_lock);
......@@ -87,12 +86,11 @@ static void mac_esp_dma_invalidate(struct esp *esp)
static int mac_esp_dma_error(struct esp *esp)
{
return MAC_ESP_GET_PRIV(esp)->error;
return esp->send_cmd_error;
}
static inline int mac_esp_wait_for_empty_fifo(struct esp *esp)
{
struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
int i = 500000;
do {
......@@ -107,7 +105,7 @@ static inline int mac_esp_wait_for_empty_fifo(struct esp *esp)
printk(KERN_ERR PFX "FIFO is not empty (sreg %02x)\n",
esp_read8(ESP_STATUS));
mep->error = 1;
esp->send_cmd_error = 1;
return 1;
}
......@@ -133,7 +131,7 @@ static inline int mac_esp_wait_for_dreq(struct esp *esp)
printk(KERN_ERR PFX "PDMA timeout (sreg %02x)\n",
esp_read8(ESP_STATUS));
mep->error = 1;
esp->send_cmd_error = 1;
return 1;
}
......@@ -200,7 +198,7 @@ static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count,
{
struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
mep->error = 0;
esp->send_cmd_error = 0;
if (!write)
scsi_esp_cmd(esp, ESP_CMD_FLUSH);
......@@ -238,166 +236,6 @@ static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count,
} while (esp_count);
}
/*
* Programmed IO routines follow.
*/
static inline unsigned int mac_esp_wait_for_fifo(struct esp *esp)
{
int i = 500000;
do {
unsigned int fbytes = esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES;
if (fbytes)
return fbytes;
udelay(2);
} while (--i);
printk(KERN_ERR PFX "FIFO is empty (sreg %02x)\n",
esp_read8(ESP_STATUS));
return 0;
}
static inline int mac_esp_wait_for_intr(struct esp *esp)
{
struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
int i = 500000;
do {
esp->sreg = esp_read8(ESP_STATUS);
if (esp->sreg & ESP_STAT_INTR)
return 0;
udelay(2);
} while (--i);
printk(KERN_ERR PFX "IRQ timeout (sreg %02x)\n", esp->sreg);
mep->error = 1;
return 1;
}
#define MAC_ESP_PIO_LOOP(operands, reg1) \
asm volatile ( \
"1: moveb " operands " \n" \
" subqw #1,%1 \n" \
" jbne 1b \n" \
: "+a" (addr), "+r" (reg1) \
: "a" (fifo))
#define MAC_ESP_PIO_FILL(operands, reg1) \
asm volatile ( \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" subqw #8,%1 \n" \
" subqw #8,%1 \n" \
: "+a" (addr), "+r" (reg1) \
: "a" (fifo))
#define MAC_ESP_FIFO_SIZE 16
static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
u32 dma_count, int write, u8 cmd)
{
struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
u8 __iomem *fifo = esp->regs + ESP_FDATA * 16;
u8 phase = esp->sreg & ESP_STAT_PMASK;
cmd &= ~ESP_CMD_DMA;
mep->error = 0;
if (write) {
u8 *dst = (u8 *)addr;
u8 mask = ~(phase == ESP_MIP ? ESP_INTR_FDONE : ESP_INTR_BSERV);
scsi_esp_cmd(esp, cmd);
while (1) {
if (!mac_esp_wait_for_fifo(esp))
break;
*dst++ = esp_read8(ESP_FDATA);
--esp_count;
if (!esp_count)
break;
if (mac_esp_wait_for_intr(esp))
break;
if ((esp->sreg & ESP_STAT_PMASK) != phase)
break;
esp->ireg = esp_read8(ESP_INTRPT);
if (esp->ireg & mask) {
mep->error = 1;
break;
}
if (phase == ESP_MIP)
scsi_esp_cmd(esp, ESP_CMD_MOK);
scsi_esp_cmd(esp, ESP_CMD_TI);
}
} else {
scsi_esp_cmd(esp, ESP_CMD_FLUSH);
if (esp_count >= MAC_ESP_FIFO_SIZE)
MAC_ESP_PIO_FILL("%0@+,%2@", esp_count);
else
MAC_ESP_PIO_LOOP("%0@+,%2@", esp_count);
scsi_esp_cmd(esp, cmd);
while (esp_count) {
unsigned int n;
if (mac_esp_wait_for_intr(esp))
break;
if ((esp->sreg & ESP_STAT_PMASK) != phase)
break;
esp->ireg = esp_read8(ESP_INTRPT);
if (esp->ireg & ~ESP_INTR_BSERV) {
mep->error = 1;
break;
}
n = MAC_ESP_FIFO_SIZE -
(esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES);
if (n > esp_count)
n = esp_count;
if (n == MAC_ESP_FIFO_SIZE) {
MAC_ESP_PIO_FILL("%0@+,%2@", esp_count);
} else {
esp_count -= n;
MAC_ESP_PIO_LOOP("%0@+,%2@", n);
}
scsi_esp_cmd(esp, ESP_CMD_TI);
}
}
esp->send_cmd_residual = esp_count;
}
static int mac_esp_irq_pending(struct esp *esp)
{
if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
......@@ -516,6 +354,7 @@ static int esp_mac_probe(struct platform_device *dev)
mep->pdma_regs = NULL;
break;
}
esp->fifo_reg = esp->regs + ESP_FDATA * 16;
esp->ops = &mac_esp_ops;
esp->flags = ESP_FLAG_NO_DMA_MAP;
......@@ -524,7 +363,7 @@ static int esp_mac_probe(struct platform_device *dev)
esp_write8(0, ESP_TCLOW);
esp_write8(0, ESP_TCMED);
esp->flags |= ESP_FLAG_DISABLE_SYNC;
mac_esp_ops.send_dma_cmd = mac_esp_send_pio_cmd;
mac_esp_ops.send_dma_cmd = esp_send_pio_cmd;
} else {
printk(KERN_INFO PFX "using PDMA for controller %d\n", dev->id);
}
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment