Commit e241138a authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://gkernel.bkbits.net/libata-2.5

into home.osdl.org:/home/torvalds/v2.5/linux
parents 7629bad2 a76a8a35
...@@ -97,6 +97,7 @@ static Scsi_Host_Template piix_sht = { ...@@ -97,6 +97,7 @@ static Scsi_Host_Template piix_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
}; };
static struct ata_port_operations piix_pata_ops = { static struct ata_port_operations piix_pata_ops = {
......
...@@ -1619,7 +1619,7 @@ static void ata_dev_set_pio(struct ata_port *ap, unsigned int device) ...@@ -1619,7 +1619,7 @@ static void ata_dev_set_pio(struct ata_port *ap, unsigned int device)
static void ata_sg_clean(struct ata_queued_cmd *qc) static void ata_sg_clean(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
Scsi_Cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
struct scatterlist *sg = qc->sg; struct scatterlist *sg = qc->sg;
int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
...@@ -1635,8 +1635,8 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) ...@@ -1635,8 +1635,8 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
if (cmd->use_sg) if (cmd->use_sg)
pci_unmap_sg(ap->host_set->pdev, sg, qc->n_elem, dir); pci_unmap_sg(ap->host_set->pdev, sg, qc->n_elem, dir);
else else
pci_unmap_single(ap->host_set->pdev, sg[0].dma_address, pci_unmap_single(ap->host_set->pdev, sg_dma_address(&sg[0]),
sg[0].length, dir); sg_dma_len(&sg[0]), dir);
qc->flags &= ~ATA_QCFLAG_SG; qc->flags &= ~ATA_QCFLAG_SG;
qc->sg = NULL; qc->sg = NULL;
...@@ -1659,8 +1659,8 @@ void ata_fill_sg(struct ata_queued_cmd *qc) ...@@ -1659,8 +1659,8 @@ void ata_fill_sg(struct ata_queued_cmd *qc)
assert(qc->n_elem > 0); assert(qc->n_elem > 0);
for (i = 0; i < qc->n_elem; i++) { for (i = 0; i < qc->n_elem; i++) {
ap->prd[i].addr = cpu_to_le32(sg[i].dma_address); ap->prd[i].addr = cpu_to_le32(sg_dma_address(&sg[i]));
ap->prd[i].flags_len = cpu_to_le32(sg[i].length); ap->prd[i].flags_len = cpu_to_le32(sg_dma_len(&sg[i]));
VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", VPRINTK("PRD[%u] = (0x%X, 0x%X)\n",
i, le32_to_cpu(ap->prd[i].addr), le32_to_cpu(ap->prd[i].flags_len)); i, le32_to_cpu(ap->prd[i].addr), le32_to_cpu(ap->prd[i].flags_len));
} }
...@@ -1681,7 +1681,7 @@ void ata_fill_sg(struct ata_queued_cmd *qc) ...@@ -1681,7 +1681,7 @@ void ata_fill_sg(struct ata_queued_cmd *qc)
static int ata_sg_setup_one(struct ata_queued_cmd *qc) static int ata_sg_setup_one(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
Scsi_Cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
struct scatterlist *sg = qc->sg; struct scatterlist *sg = qc->sg;
unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG); unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
...@@ -1691,12 +1691,12 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) ...@@ -1691,12 +1691,12 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
sg->page = virt_to_page(cmd->request_buffer); sg->page = virt_to_page(cmd->request_buffer);
sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK; sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK;
sg->length = cmd->request_bufflen; sg_dma_len(sg) = cmd->request_bufflen;
if (!have_sg) if (!have_sg)
return 0; return 0;
sg->dma_address = pci_map_single(ap->host_set->pdev, sg_dma_address(sg) = pci_map_single(ap->host_set->pdev,
cmd->request_buffer, cmd->request_buffer,
cmd->request_bufflen, dir); cmd->request_bufflen, dir);
...@@ -1720,7 +1720,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) ...@@ -1720,7 +1720,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
static int ata_sg_setup(struct ata_queued_cmd *qc) static int ata_sg_setup(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
Scsi_Cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
struct scatterlist *sg; struct scatterlist *sg;
int n_elem; int n_elem;
unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG); unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
...@@ -1872,7 +1872,7 @@ static void ata_pio_sector(struct ata_port *ap) ...@@ -1872,7 +1872,7 @@ static void ata_pio_sector(struct ata_port *ap)
{ {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
struct scatterlist *sg; struct scatterlist *sg;
Scsi_Cmnd *cmd; struct scsi_cmnd *cmd;
unsigned char *buf; unsigned char *buf;
u8 status; u8 status;
...@@ -1917,7 +1917,7 @@ static void ata_pio_sector(struct ata_port *ap) ...@@ -1917,7 +1917,7 @@ static void ata_pio_sector(struct ata_port *ap)
qc->cursg_ofs++; qc->cursg_ofs++;
if (cmd->use_sg) if (cmd->use_sg)
if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg[qc->cursg].length) { if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) {
qc->cursg++; qc->cursg++;
qc->cursg_ofs = 0; qc->cursg_ofs = 0;
} }
...@@ -2092,7 +2092,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, ...@@ -2092,7 +2092,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat, unsigned int done_late) void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat, unsigned int done_late)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
Scsi_Cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
unsigned int tag, do_clear = 0; unsigned int tag, do_clear = 0;
assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */
...@@ -2163,7 +2163,7 @@ static void ata_qc_push (struct ata_queued_cmd *qc, unsigned int append) ...@@ -2163,7 +2163,7 @@ static void ata_qc_push (struct ata_queued_cmd *qc, unsigned int append)
int ata_qc_issue(struct ata_queued_cmd *qc) int ata_qc_issue(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
Scsi_Cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
unsigned int dma = qc->flags & ATA_QCFLAG_DMA; unsigned int dma = qc->flags & ATA_QCFLAG_DMA;
ata_dev_select(ap, qc->dev->devno, 1, 0); ata_dev_select(ap, qc->dev->devno, 1, 0);
...@@ -2719,7 +2719,7 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister) ...@@ -2719,7 +2719,7 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
if (do_unregister) if (do_unregister)
scsi_remove_host(sh); /* FIXME: check return val */ scsi_remove_host(sh);
ata_thread_kill(ap); /* FIXME: check return val */ ata_thread_kill(ap); /* FIXME: check return val */
...@@ -3204,7 +3204,6 @@ void ata_pci_remove_one (struct pci_dev *pdev) ...@@ -3204,7 +3204,6 @@ void ata_pci_remove_one (struct pci_dev *pdev)
for (i = 0; i < host_set->n_ports; i++) { for (i = 0; i < host_set->n_ports; i++) {
ap = host_set->ports[i]; ap = host_set->ports[i];
/* FIXME: check return val */
scsi_remove_host(ap->host); scsi_remove_host(ap->host);
} }
...@@ -3215,13 +3214,10 @@ void ata_pci_remove_one (struct pci_dev *pdev) ...@@ -3215,13 +3214,10 @@ void ata_pci_remove_one (struct pci_dev *pdev)
host_set->ports[0]->ops->host_stop(host_set); host_set->ports[0]->ops->host_stop(host_set);
for (i = 0; i < host_set->n_ports; i++) { for (i = 0; i < host_set->n_ports; i++) {
Scsi_Host_Template *sht;
ap = host_set->ports[i]; ap = host_set->ports[i];
sht = ap->host->hostt;
ata_scsi_release(ap->host); ata_scsi_release(ap->host);
scsi_host_put(ap->host); /* FIXME: check return val */ scsi_host_put(ap->host);
} }
pci_release_regions(pdev); pci_release_regions(pdev);
...@@ -3279,6 +3275,7 @@ int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits) ...@@ -3279,6 +3275,7 @@ int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits)
return (tmp == bits->val) ? 1 : 0; return (tmp == bits->val) ? 1 : 0;
} }
/** /**
* ata_init - * ata_init -
* *
...@@ -3304,6 +3301,7 @@ module_init(ata_init); ...@@ -3304,6 +3301,7 @@ module_init(ata_init);
*/ */
EXPORT_SYMBOL_GPL(pci_test_config_bits); EXPORT_SYMBOL_GPL(pci_test_config_bits);
EXPORT_SYMBOL_GPL(ata_std_bios_param);
EXPORT_SYMBOL_GPL(ata_std_ports); EXPORT_SYMBOL_GPL(ata_std_ports);
EXPORT_SYMBOL_GPL(ata_device_add); EXPORT_SYMBOL_GPL(ata_device_add);
EXPORT_SYMBOL_GPL(ata_qc_complete); EXPORT_SYMBOL_GPL(ata_qc_complete);
......
...@@ -32,10 +32,33 @@ ...@@ -32,10 +32,33 @@
#include "libata.h" #include "libata.h"
/**
* ata_std_bios_param - generic bios head/sector/cylinder calculator
* used by sd. Most BIOSes nowadays expect a XXX/255/16 (CHS)
* mapping. Some situations may arise where the disk is not
* bootable if this is not used.
*
* LOCKING:
*
* RETURNS:
*
*/
int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int geom[])
{
geom[0] = 255;
geom[1] = 63;
geom[2] = capacity / (geom[0] * geom[1]);
return 0;
}
struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap, struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
struct ata_device *dev, struct ata_device *dev,
Scsi_Cmnd *cmd, struct scsi_cmnd *cmd,
void (*done)(Scsi_Cmnd *)) void (*done)(struct scsi_cmnd *))
{ {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
...@@ -69,7 +92,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap, ...@@ -69,7 +92,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
void ata_to_sense_error(struct ata_queued_cmd *qc) void ata_to_sense_error(struct ata_queued_cmd *qc)
{ {
Scsi_Cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
cmd->result = SAM_STAT_CHECK_CONDITION; cmd->result = SAM_STAT_CHECK_CONDITION;
...@@ -282,7 +305,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd, ...@@ -282,7 +305,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd,
*/ */
void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev, void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev,
Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *), struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
unsigned int cmd_size) unsigned int cmd_size)
{ {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
...@@ -332,7 +355,7 @@ void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev, ...@@ -332,7 +355,7 @@ void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev,
* Length of response buffer. * Length of response buffer.
*/ */
static unsigned int ata_scsi_rbuf_get(Scsi_Cmnd *cmd, u8 **buf_out) static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
{ {
u8 *buf; u8 *buf;
unsigned int buflen; unsigned int buflen;
...@@ -363,7 +386,7 @@ static unsigned int ata_scsi_rbuf_get(Scsi_Cmnd *cmd, u8 **buf_out) ...@@ -363,7 +386,7 @@ static unsigned int ata_scsi_rbuf_get(Scsi_Cmnd *cmd, u8 **buf_out)
* spin_lock_irqsave(host_set lock) * spin_lock_irqsave(host_set lock)
*/ */
static inline void ata_scsi_rbuf_put(Scsi_Cmnd *cmd) static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd)
{ {
if (cmd->use_sg) { if (cmd->use_sg) {
struct scatterlist *sg; struct scatterlist *sg;
...@@ -394,7 +417,7 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args, ...@@ -394,7 +417,7 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
{ {
u8 *rbuf; u8 *rbuf;
unsigned int buflen, rc; unsigned int buflen, rc;
Scsi_Cmnd *cmd = args->cmd; struct scsi_cmnd *cmd = args->cmd;
buflen = ata_scsi_rbuf_get(cmd, &rbuf); buflen = ata_scsi_rbuf_get(cmd, &rbuf);
rc = actor(args, rbuf, buflen); rc = actor(args, rbuf, buflen);
...@@ -817,7 +840,7 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf, ...@@ -817,7 +840,7 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
* spin_lock_irqsave(host_set lock) * spin_lock_irqsave(host_set lock)
*/ */
void ata_scsi_badcmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *), u8 asc, u8 ascq) void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
{ {
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
cmd->result = SAM_STAT_CHECK_CONDITION; cmd->result = SAM_STAT_CHECK_CONDITION;
...@@ -847,7 +870,7 @@ void ata_scsi_badcmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *), u8 asc, u8 ascq) ...@@ -847,7 +870,7 @@ void ata_scsi_badcmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *), u8 asc, u8 ascq)
*/ */
static void atapi_scsi_queuecmd(struct ata_port *ap, struct ata_device *dev, static void atapi_scsi_queuecmd(struct ata_port *ap, struct ata_device *dev,
Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{ {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
u8 *scsicmd = cmd->cmnd, status; u8 *scsicmd = cmd->cmnd, status;
...@@ -958,7 +981,7 @@ static void atapi_scsi_queuecmd(struct ata_port *ap, struct ata_device *dev, ...@@ -958,7 +981,7 @@ static void atapi_scsi_queuecmd(struct ata_port *ap, struct ata_device *dev,
* Zero. * Zero.
*/ */
int ata_scsi_queuecmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{ {
u8 *scsicmd = cmd->cmnd; u8 *scsicmd = cmd->cmnd;
struct ata_port *ap; struct ata_port *ap;
......
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
struct ata_scsi_args { struct ata_scsi_args {
struct ata_port *ap; struct ata_port *ap;
struct ata_device *dev; struct ata_device *dev;
Scsi_Cmnd *cmd; struct scsi_cmnd *cmd;
void (*done)(Scsi_Cmnd *); void (*done)(struct scsi_cmnd *);
}; };
...@@ -51,7 +51,7 @@ extern void ata_thread_wake(struct ata_port *ap, unsigned int thr_state); ...@@ -51,7 +51,7 @@ extern void ata_thread_wake(struct ata_port *ap, unsigned int thr_state);
/* libata-scsi.c */ /* libata-scsi.c */
extern void ata_to_sense_error(struct ata_queued_cmd *qc); extern void ata_to_sense_error(struct ata_queued_cmd *qc);
extern void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev, extern void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev,
Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *), struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
unsigned int cmd_size); unsigned int cmd_size);
extern int ata_scsi_error(struct Scsi_Host *host); extern int ata_scsi_error(struct Scsi_Host *host);
extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
...@@ -74,19 +74,19 @@ extern unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, ...@@ -74,19 +74,19 @@ extern unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen); unsigned int buflen);
extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf, extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen); unsigned int buflen);
extern void ata_scsi_badcmd(Scsi_Cmnd *cmd, extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
void (*done)(Scsi_Cmnd *), void (*done)(struct scsi_cmnd *),
u8 asc, u8 ascq); u8 asc, u8 ascq);
extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
unsigned int (*actor) (struct ata_scsi_args *args, unsigned int (*actor) (struct ata_scsi_args *args,
u8 *rbuf, unsigned int buflen)); u8 *rbuf, unsigned int buflen));
static inline void ata_bad_scsiop(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) static inline void ata_bad_scsiop(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{ {
ata_scsi_badcmd(cmd, done, 0x20, 0x00); ata_scsi_badcmd(cmd, done, 0x20, 0x00);
} }
static inline void ata_bad_cdb(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) static inline void ata_bad_cdb(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{ {
ata_scsi_badcmd(cmd, done, 0x24, 0x00); ata_scsi_badcmd(cmd, done, 0x24, 0x00);
} }
......
...@@ -34,10 +34,8 @@ ...@@ -34,10 +34,8 @@
#include <linux/libata.h> #include <linux/libata.h>
#include <asm/io.h> #include <asm/io.h>
#undef DIRECT_HDMA
#define DRV_NAME "sata_promise" #define DRV_NAME "sata_promise"
#define DRV_VERSION "0.86" #define DRV_VERSION "0.89"
enum { enum {
...@@ -82,6 +80,42 @@ enum { ...@@ -82,6 +80,42 @@ enum {
PDC_FLAG_20621 = (1 << 30), /* we have a 20621 */ PDC_FLAG_20621 = (1 << 30), /* we have a 20621 */
PDC_HDMA_RESET = (1 << 11), /* HDMA reset */ PDC_HDMA_RESET = (1 << 11), /* HDMA reset */
PDC_MAX_HDMA = 32,
PDC_HDMA_Q_MASK = (PDC_MAX_HDMA - 1),
PDC_DIMM0_SPD_DEV_ADDRESS = 0x50,
PDC_DIMM1_SPD_DEV_ADDRESS = 0x51,
PDC_MAX_DIMM_MODULE = 0x02,
PDC_I2C_CONTROL_OFFSET = 0x48,
PDC_I2C_ADDR_DATA_OFFSET = 0x4C,
PDC_DIMM0_CONTROL_OFFSET = 0x80,
PDC_DIMM1_CONTROL_OFFSET = 0x84,
PDC_SDRAM_CONTROL_OFFSET = 0x88,
PDC_I2C_WRITE = 0x00000000,
PDC_I2C_READ = 0x00000040,
PDC_I2C_START = 0x00000080,
PDC_I2C_MASK_INT = 0x00000020,
PDC_I2C_COMPLETE = 0x00010000,
PDC_I2C_NO_ACK = 0x00100000,
PDC_DIMM_SPD_SUBADDRESS_START = 0x00,
PDC_DIMM_SPD_SUBADDRESS_END = 0x7F,
PDC_DIMM_SPD_ROW_NUM = 3,
PDC_DIMM_SPD_COLUMN_NUM = 4,
PDC_DIMM_SPD_MODULE_ROW = 5,
PDC_DIMM_SPD_TYPE = 11,
PDC_DIMM_SPD_FRESH_RATE = 12,
PDC_DIMM_SPD_BANK_NUM = 17,
PDC_DIMM_SPD_CAS_LATENCY = 18,
PDC_DIMM_SPD_ATTRIBUTE = 21,
PDC_DIMM_SPD_ROW_PRE_CHARGE = 27,
PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
PDC_DIMM_SPD_RAS_CAS_DELAY = 29,
PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
PDC_DIMM_SPD_SYSTEM_FREQ = 126,
PDC_CTL_STATUS = 0x08,
PDC_DIMM_WINDOW_CTLR = 0x0C,
PDC_GENERAL_CTLR = 0x484,
}; };
...@@ -91,6 +125,19 @@ struct pdc_port_priv { ...@@ -91,6 +125,19 @@ struct pdc_port_priv {
dma_addr_t pkt_dma; dma_addr_t pkt_dma;
}; };
struct pdc_host_priv {
void *dimm_mmio;
unsigned int doing_hdma;
unsigned int hdma_prod;
unsigned int hdma_cons;
struct {
struct ata_queued_cmd *qc;
unsigned int seq;
unsigned long pkt_ofs;
} hdma[32];
};
static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg); static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
...@@ -114,6 +161,18 @@ static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); ...@@ -114,6 +161,18 @@ static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
static void pdc20621_host_stop(struct ata_host_set *host_set); static void pdc20621_host_stop(struct ata_host_set *host_set);
static inline void pdc_dma_complete (struct ata_port *ap, static inline void pdc_dma_complete (struct ata_port *ap,
struct ata_queued_cmd *qc); struct ata_queued_cmd *qc);
static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe,
u32 device, u32 subaddr, u32 *pdata);
static int pdc20621_prog_dimm0(struct ata_probe_ent *pe);
static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe);
#ifdef ATA_VERBOSE_DEBUG
static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
void *psource, u32 offset, u32 size);
#endif
static void pdc20621_put_to_dimm(struct ata_probe_ent *pe,
void *psource, u32 offset, u32 size);
static Scsi_Host_Template pdc_sata_sht = { static Scsi_Host_Template pdc_sata_sht = {
...@@ -131,6 +190,7 @@ static Scsi_Host_Template pdc_sata_sht = { ...@@ -131,6 +190,7 @@ static Scsi_Host_Template pdc_sata_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
}; };
static struct ata_port_operations pdc_sata_ops = { static struct ata_port_operations pdc_sata_ops = {
...@@ -235,10 +295,11 @@ static struct pci_driver pdc_sata_pci_driver = { ...@@ -235,10 +295,11 @@ static struct pci_driver pdc_sata_pci_driver = {
static void pdc20621_host_stop(struct ata_host_set *host_set) static void pdc20621_host_stop(struct ata_host_set *host_set)
{ {
void *mmio = host_set->private_data; struct pdc_host_priv *hpriv = host_set->private_data;
void *dimm_mmio = hpriv->dimm_mmio;
assert(mmio != NULL); iounmap(dimm_mmio);
iounmap(mmio); kfree(hpriv);
} }
static int pdc_port_start(struct ata_port *ap) static int pdc_port_start(struct ata_port *ap)
...@@ -256,6 +317,7 @@ static int pdc_port_start(struct ata_port *ap) ...@@ -256,6 +317,7 @@ static int pdc_port_start(struct ata_port *ap)
rc = -ENOMEM; rc = -ENOMEM;
goto err_out; goto err_out;
} }
memset(pp, 0, sizeof(*pp));
pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma); pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma);
if (!pp->pkt) { if (!pp->pkt) {
...@@ -589,7 +651,8 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc) ...@@ -589,7 +651,8 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
struct pdc_port_priv *pp = ap->private_data; struct pdc_port_priv *pp = ap->private_data;
void *mmio = ap->host_set->mmio_base; void *mmio = ap->host_set->mmio_base;
void *dimm_mmio = ap->host_set->private_data; struct pdc_host_priv *hpriv = ap->host_set->private_data;
void *dimm_mmio = hpriv->dimm_mmio;
unsigned int portno = ap->port_no; unsigned int portno = ap->port_no;
unsigned int i, last, idx, total_len = 0, sgt_len; unsigned int i, last, idx, total_len = 0, sgt_len;
u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ]; u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
...@@ -605,8 +668,8 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc) ...@@ -605,8 +668,8 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc)
last = qc->n_elem; last = qc->n_elem;
idx = 0; idx = 0;
for (i = 0; i < last; i++) { for (i = 0; i < last; i++) {
buf[idx++] = cpu_to_le32(sg[i].dma_address); buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i]));
buf[idx++] = cpu_to_le32(sg[i].length); buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i]));
total_len += sg[i].length; total_len += sg[i].length;
} }
buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT); buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT);
...@@ -643,49 +706,68 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc) ...@@ -643,49 +706,68 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc)
VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len); VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len);
} }
#ifdef DIRECT_HDMA static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
static void pdc20621_push_hdma(struct ata_queued_cmd *qc) unsigned int seq,
u32 pkt_ofs)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
struct ata_host_set *host_set = ap->host_set; struct ata_host_set *host_set = ap->host_set;
unsigned int port_no = ap->port_no;
void *mmio = host_set->mmio_base; void *mmio = host_set->mmio_base;
unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE);
u32 tmp;
unsigned int host_sg = PDC_20621_DIMM_BASE +
(PDC_DIMM_WINDOW_STEP * port_no) +
PDC_DIMM_HOST_PRD;
unsigned int dimm_sg = PDC_20621_DIMM_BASE +
(PDC_DIMM_WINDOW_STEP * port_no) +
PDC_DIMM_HPKT_PRD;
/* hard-code chip #0 */ /* hard-code chip #0 */
mmio += PDC_CHIP0_OFS; mmio += PDC_CHIP0_OFS;
tmp = readl(mmio + PDC_HDMA_CTLSTAT) & 0xffffff00; writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
tmp |= port_no + 1 + 4; /* seq. ID */ readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */
if (!rw)
tmp |= (1 << 6); /* hdma data direction */
writel(tmp, mmio + PDC_HDMA_CTLSTAT); /* note: stops DMA, if active */
readl(mmio + PDC_HDMA_CTLSTAT); /* flush */
writel(host_sg, mmio + 0x108); writel(pkt_ofs, mmio + PDC_HDMA_PKT_SUBMIT);
writel(dimm_sg, mmio + 0x10C); readl(mmio + PDC_HDMA_PKT_SUBMIT); /* flush */
writel(0, mmio + 0x128); }
tmp |= (1 << 7); static void pdc20621_push_hdma(struct ata_queued_cmd *qc,
writel(tmp, mmio + PDC_HDMA_CTLSTAT); unsigned int seq,
readl(mmio + PDC_HDMA_CTLSTAT); /* flush */ u32 pkt_ofs)
{
struct ata_port *ap = qc->ap;
struct pdc_host_priv *pp = ap->host_set->private_data;
unsigned int idx = pp->hdma_prod & PDC_HDMA_Q_MASK;
if (!pp->doing_hdma) {
__pdc20621_push_hdma(qc, seq, pkt_ofs);
pp->doing_hdma = 1;
return;
}
pp->hdma[idx].qc = qc;
pp->hdma[idx].seq = seq;
pp->hdma[idx].pkt_ofs = pkt_ofs;
pp->hdma_prod++;
}
static void pdc20621_pop_hdma(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct pdc_host_priv *pp = ap->host_set->private_data;
unsigned int idx = pp->hdma_cons & PDC_HDMA_Q_MASK;
/* if nothing on queue, we're done */
if (pp->hdma_prod == pp->hdma_cons) {
pp->doing_hdma = 0;
return;
}
__pdc20621_push_hdma(pp->hdma[idx].qc, pp->hdma[idx].seq,
pp->hdma[idx].pkt_ofs);
pp->hdma_cons++;
} }
#endif
#ifdef ATA_VERBOSE_DEBUG #ifdef ATA_VERBOSE_DEBUG
static void pdc20621_dump_hdma(struct ata_queued_cmd *qc) static void pdc20621_dump_hdma(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
unsigned int port_no = ap->port_no; unsigned int port_no = ap->port_no;
void *dimm_mmio = ap->host_set->private_data; struct pdc_host_priv *hpriv = ap->host_set->private_data;
void *dimm_mmio = hpriv->dimm_mmio;
dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP); dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP);
dimm_mmio += PDC_DIMM_HOST_PKT; dimm_mmio += PDC_DIMM_HOST_PKT;
...@@ -724,23 +806,17 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc) ...@@ -724,23 +806,17 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc)
wmb(); /* flush PRD, pkt writes */ wmb(); /* flush PRD, pkt writes */
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */
if (doing_hdma) { if (doing_hdma) {
pdc20621_dump_hdma(qc); pdc20621_dump_hdma(qc);
#ifdef DIRECT_HDMA pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT);
pdc20621_push_hdma(qc); VPRINTK("queued ofs 0x%x (%u), seq %u\n",
#else
writel(port_ofs + PDC_DIMM_HOST_PKT,
mmio + PDC_HDMA_PKT_SUBMIT);
readl(mmio + PDC_HDMA_PKT_SUBMIT); /* flush */
#endif
VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
port_ofs + PDC_DIMM_HOST_PKT, port_ofs + PDC_DIMM_HOST_PKT,
port_ofs + PDC_DIMM_HOST_PKT, port_ofs + PDC_DIMM_HOST_PKT,
seq); seq);
} else { } else {
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */
writel(port_ofs + PDC_DIMM_ATA_PKT, writel(port_ofs + PDC_DIMM_ATA_PKT,
(void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
...@@ -771,6 +847,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, ...@@ -771,6 +847,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id, VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
pdc_dma_complete(ap, qc); pdc_dma_complete(ap, qc);
pdc20621_pop_hdma(qc);
} }
/* step one - exec ATA command */ /* step one - exec ATA command */
...@@ -781,15 +858,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, ...@@ -781,15 +858,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
/* submit hdma pkt */ /* submit hdma pkt */
pdc20621_dump_hdma(qc); pdc20621_dump_hdma(qc);
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); pdc20621_push_hdma(qc, seq,
readl(mmio + PDC_20621_SEQCTL + (seq * 4)); port_ofs + PDC_DIMM_HOST_PKT);
#ifdef DIRECT_HDMA
pdc20621_push_hdma(qc);
#else
writel(port_ofs + PDC_DIMM_HOST_PKT,
mmio + PDC_HDMA_PKT_SUBMIT);
readl(mmio + PDC_HDMA_PKT_SUBMIT);
#endif
} }
handled = 1; handled = 1;
break; break;
...@@ -814,6 +884,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, ...@@ -814,6 +884,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id, VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
pdc_dma_complete(ap, qc); pdc_dma_complete(ap, qc);
pdc20621_pop_hdma(qc);
} }
handled = 1; handled = 1;
break; break;
...@@ -1098,11 +1169,373 @@ static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base) ...@@ -1098,11 +1169,373 @@ static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
port->ctl_addr = base + 0x38; port->ctl_addr = base + 0x38;
} }
#ifdef ATA_VERBOSE_DEBUG
static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
u32 offset, u32 size)
{
u32 window_size;
u16 idx;
u8 page_mask;
long dist;
void *mmio = pe->mmio_base;
struct pdc_host_priv *hpriv = pe->private_data;
void *dimm_mmio = hpriv->dimm_mmio;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
page_mask = 0x00;
window_size = 0x2000 * 4; /* 32K byte uchar size */
idx = (u16) (offset / window_size);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
offset -= (idx * window_size);
idx++;
dist = ((long) (window_size - (offset + size))) >= 0 ? size :
(long) (window_size - offset);
memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4),
dist);
psource += dist;
size -= dist;
for (; (long) size >= (long) window_size ;) {
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
memcpy_fromio((char *) psource, (char *) (dimm_mmio),
window_size / 4);
psource += window_size;
size -= window_size;
idx ++;
}
if (size) {
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
memcpy_fromio((char *) psource, (char *) (dimm_mmio),
size / 4);
}
}
#endif
static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
u32 offset, u32 size)
{
u32 window_size;
u16 idx;
u8 page_mask;
long dist;
void *mmio = pe->mmio_base;
struct pdc_host_priv *hpriv = pe->private_data;
void *dimm_mmio = hpriv->dimm_mmio;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
page_mask = 0x00;
window_size = 0x2000 * 4; /* 32K byte uchar size */
idx = (u16) (offset / window_size);
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
offset -= (idx * window_size);
idx++;
dist = ((long) (window_size - (offset + size))) >= 0 ? size :
(long) (window_size - offset);
memcpy_toio((char *) (dimm_mmio + offset / 4), (char *) psource, dist);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
psource += dist;
size -= dist;
for (; (long) size >= (long) window_size ;) {
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
memcpy_toio((char *) (dimm_mmio), (char *) psource,
window_size / 4);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
psource += window_size;
size -= window_size;
idx ++;
}
if (size) {
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
memcpy_toio((char *) (dimm_mmio), (char *) psource, size / 4);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
}
}
static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
u32 subaddr, u32 *pdata)
{
void *mmio = pe->mmio_base;
u32 i2creg = 0;
u32 status;
u32 count =0;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
i2creg |= device << 24;
i2creg |= subaddr << 16;
/* Set the device and subaddress */
writel(i2creg, mmio + PDC_I2C_ADDR_DATA_OFFSET);
readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
/* Write Control to perform read operation, mask int */
writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT,
mmio + PDC_I2C_CONTROL_OFFSET);
for (count = 0; count <= 1000; count ++) {
status = readl(mmio + PDC_I2C_CONTROL_OFFSET);
if (status & PDC_I2C_COMPLETE) {
status = readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
break;
} else if (count == 1000)
return 0;
}
*pdata = (status >> 8) & 0x000000ff;
return 1;
}
static int pdc20621_detect_dimm(struct ata_probe_ent *pe)
{
u32 data=0 ;
if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_SYSTEM_FREQ, &data)) {
if (data == 100)
return 100;
} else
return 0;
if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
if(data <= 0x75)
return 133;
} else
return 0;
return 0;
}
static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
{
u32 spd0[50];
u32 data = 0;
int size, i;
u8 bdimmsize;
void *mmio = pe->mmio_base;
static const struct {
unsigned int reg;
unsigned int ofs;
} pdc_i2c_read_data [] = {
{ PDC_DIMM_SPD_TYPE, 11 },
{ PDC_DIMM_SPD_FRESH_RATE, 12 },
{ PDC_DIMM_SPD_COLUMN_NUM, 4 },
{ PDC_DIMM_SPD_ATTRIBUTE, 21 },
{ PDC_DIMM_SPD_ROW_NUM, 3 },
{ PDC_DIMM_SPD_BANK_NUM, 17 },
{ PDC_DIMM_SPD_MODULE_ROW, 5 },
{ PDC_DIMM_SPD_ROW_PRE_CHARGE, 27 },
{ PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 },
{ PDC_DIMM_SPD_RAS_CAS_DELAY, 29 },
{ PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 },
{ PDC_DIMM_SPD_CAS_LATENCY, 18 },
};
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++)
pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
pdc_i2c_read_data[i].reg,
&spd0[pdc_i2c_read_data[i].ofs]);
data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4);
data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) |
((((spd0[27] + 9) / 10) - 1) << 8) ;
data |= (((((spd0[29] > spd0[28])
? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10;
data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12;
if (spd0[18] & 0x08)
data |= ((0x03) << 14);
else if (spd0[18] & 0x04)
data |= ((0x02) << 14);
else if (spd0[18] & 0x01)
data |= ((0x01) << 14);
else
data |= (0 << 14);
/*
Calculate the size of bDIMMSize (power of 2) and
merge the DIMM size by program start/end address.
*/
bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3;
size = (1 << bdimmsize) >> 20; /* size = xxx(MB) */
data |= (((size / 16) - 1) << 16);
data |= (0 << 23);
data |= 8;
writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET);
readl(mmio + PDC_DIMM0_CONTROL_OFFSET);
return size;
}
static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
{
u32 data, spd0;
int error, i;
void *mmio = pe->mmio_base;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
/*
Set To Default : DIMM Module Global Control Register (0x022259F1)
DIMM Arbitration Disable (bit 20)
DIMM Data/Control Output Driving Selection (bit12 - bit15)
Refresh Enable (bit 17)
*/
data = 0x022259F1;
writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
/* Turn on for ECC */
pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_TYPE, &spd0);
if (spd0 == 0x02) {
data |= (0x01 << 16);
writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
printk(KERN_ERR "Local DIMM ECC Enabled\n");
}
/* DIMM Initialization Select/Enable (bit 18/19) */
data &= (~(1<<18));
data |= (1<<19);
writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
error = 1;
for (i = 1; i <= 10; i++) { /* polling ~5 secs */
data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
if (!(data & (1<<19))) {
error = 0;
break;
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout((i * 100) * HZ / 1000);
}
return error;
}
static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
{
int speed, size, length;
u32 addr,spd0,pci_status;
u32 tmp=0;
void *mmio = pe->mmio_base;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
/* Initialize PLL. */
pci_status = 0x8a531824;
writel(pci_status, mmio + PDC_CTL_STATUS);
readl(mmio + PDC_CTL_STATUS);
/*
Read SPD of DIMM by I2C interface,
and program the DIMM Module Controller.
*/
if (!(speed = pdc20621_detect_dimm(pe))) {
printk(KERN_ERR "Detect Local DIMM Fail\n");
return 1; /* DIMM error */
}
VPRINTK("Local DIMM Speed = %d\n", speed);
/* Programming DIMM0 Module Control Register (index_CID0:80h) */
size = pdc20621_prog_dimm0(pe);
VPRINTK("Local DIMM Size = %dMB\n",size);
/* Programming DIMM Module Global Control Register (index_CID0:88h) */
if (pdc20621_prog_dimm_global(pe)) {
printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n");
return 1;
}
#ifdef ATA_VERBOSE_DEBUG
{
u8 test_parttern1[40] = {0x55,0xAA,'P','r','o','m','i','s','e',' ',
'N','o','t',' ','Y','e','t',' ','D','e','f','i','n','e','d',' ',
'1','.','1','0',
'9','8','0','3','1','6','1','2',0,0};
u8 test_parttern2[40] = {0};
pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x10040, 40);
pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x40, 40);
pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40);
pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040,
40);
printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40);
pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
}
#endif
/* ECC initiliazation. */
pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_TYPE, &spd0);
if (spd0 == 0x02) {
VPRINTK("Start ECC initialization\n");
addr = 0;
length = size * 1024 * 1024;
while (addr < length) {
pdc20621_put_to_dimm(pe, (void *) &tmp, addr,
sizeof(u32));
addr += sizeof(u32);
}
VPRINTK("Finish ECC initialization\n");
}
return 0;
}
static void pdc_20621_init(struct ata_probe_ent *pe) static void pdc_20621_init(struct ata_probe_ent *pe)
{ {
u32 tmp; u32 tmp;
void *mmio = pe->mmio_base; void *mmio = pe->mmio_base;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS; mmio += PDC_CHIP0_OFS;
/* /*
...@@ -1170,6 +1603,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -1170,6 +1603,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
struct ata_probe_ent *probe_ent = NULL; struct ata_probe_ent *probe_ent = NULL;
unsigned long base; unsigned long base;
void *mmio_base, *dimm_mmio = NULL; void *mmio_base, *dimm_mmio = NULL;
struct pdc_host_priv *hpriv = NULL;
unsigned int board_idx = (unsigned int) ent->driver_data; unsigned int board_idx = (unsigned int) ent->driver_data;
unsigned int have_20621 = (board_idx == board_20621); unsigned int have_20621 = (board_idx == board_20621);
int rc; int rc;
...@@ -1212,12 +1646,22 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -1212,12 +1646,22 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
base = (unsigned long) mmio_base; base = (unsigned long) mmio_base;
if (have_20621) { if (have_20621) {
hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
if (!hpriv) {
rc = -ENOMEM;
goto err_out_iounmap;
}
memset(hpriv, 0, sizeof(*hpriv));
dimm_mmio = ioremap(pci_resource_start(pdev, 4), dimm_mmio = ioremap(pci_resource_start(pdev, 4),
pci_resource_len(pdev, 4)); pci_resource_len(pdev, 4));
if (!dimm_mmio) { if (!dimm_mmio) {
kfree(hpriv);
rc = -ENOMEM; rc = -ENOMEM;
goto err_out_iounmap; goto err_out_iounmap;
} }
hpriv->dimm_mmio = dimm_mmio;
} }
probe_ent->sht = pdc_port_info[board_idx].sht; probe_ent->sht = pdc_port_info[board_idx].sht;
...@@ -1231,7 +1675,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -1231,7 +1675,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
probe_ent->mmio_base = mmio_base; probe_ent->mmio_base = mmio_base;
if (have_20621) { if (have_20621) {
probe_ent->private_data = dimm_mmio; probe_ent->private_data = hpriv;
base += PDC_CHIP0_OFS; base += PDC_CHIP0_OFS;
} }
...@@ -1268,9 +1712,14 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -1268,9 +1712,14 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
pci_set_master(pdev); pci_set_master(pdev);
/* initialize adapter */ /* initialize adapter */
if (have_20621) if (have_20621) {
/* initialize local dimm */
if (pdc20621_dimm_init(probe_ent)) {
rc = -ENOMEM;
goto err_out_iounmap_dimm;
}
pdc_20621_init(probe_ent); pdc_20621_init(probe_ent);
else } else
pdc_host_init(board_idx, probe_ent); pdc_host_init(board_idx, probe_ent);
/* FIXME: check ata_device_add return value */ /* FIXME: check ata_device_add return value */
...@@ -1279,6 +1728,9 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -1279,6 +1728,9 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
return 0; return 0;
err_out_iounmap_dimm: /* only get to this label if 20621 */
kfree(hpriv);
iounmap(dimm_mmio);
err_out_iounmap: err_out_iounmap:
iounmap(mmio_base); iounmap(mmio_base);
err_out_free_ent: err_out_free_ent:
......
...@@ -87,6 +87,7 @@ static Scsi_Host_Template sil_sht = { ...@@ -87,6 +87,7 @@ static Scsi_Host_Template sil_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
}; };
static struct ata_port_operations sil_ops = { static struct ata_port_operations sil_ops = {
......
...@@ -219,6 +219,7 @@ static Scsi_Host_Template k2_sata_sht = { ...@@ -219,6 +219,7 @@ static Scsi_Host_Template k2_sata_sht = {
#ifdef CONFIG_ALL_PPC #ifdef CONFIG_ALL_PPC
.proc_info = k2_sata_proc_info .proc_info = k2_sata_proc_info
#endif #endif
.bios_param = ata_std_bios_param,
}; };
......
...@@ -78,6 +78,7 @@ static Scsi_Host_Template svia_sht = { ...@@ -78,6 +78,7 @@ static Scsi_Host_Template svia_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
}; };
static struct ata_port_operations svia_sata_ops = { static struct ata_port_operations svia_sata_ops = {
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <linux/ata.h> #include <linux/ata.h>
/* /*
* compile-time options * compile-time options
*/ */
...@@ -66,8 +67,6 @@ ...@@ -66,8 +67,6 @@
/* defines only for the constants which don't work well as enums */ /* defines only for the constants which don't work well as enums */
#define ATA_TAG_POISON 0xfafbfcfdU #define ATA_TAG_POISON 0xfafbfcfdU
#define ATA_DMA_BOUNDARY 0xffffUL
#define ATA_DMA_MASK 0xffffffffULL
enum { enum {
/* various global constants */ /* various global constants */
...@@ -171,6 +170,7 @@ enum { ...@@ -171,6 +170,7 @@ enum {
}; };
/* forward declarations */ /* forward declarations */
struct scsi_device;
struct ata_port_operations; struct ata_port_operations;
struct ata_port; struct ata_port;
struct ata_queued_cmd; struct ata_queued_cmd;
...@@ -247,8 +247,8 @@ struct ata_queued_cmd { ...@@ -247,8 +247,8 @@ struct ata_queued_cmd {
struct ata_port *ap; struct ata_port *ap;
struct ata_device *dev; struct ata_device *dev;
Scsi_Cmnd *scsicmd; struct scsi_cmnd *scsicmd;
void (*scsidone)(Scsi_Cmnd *); void (*scsidone)(struct scsi_cmnd *);
struct list_head node; struct list_head node;
unsigned long flags; /* ATA_QCFLAG_xxx */ unsigned long flags; /* ATA_QCFLAG_xxx */
...@@ -403,7 +403,7 @@ extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_i ...@@ -403,7 +403,7 @@ extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_i
extern void ata_pci_remove_one (struct pci_dev *pdev); extern void ata_pci_remove_one (struct pci_dev *pdev);
extern int ata_device_add(struct ata_probe_ent *ent); extern int ata_device_add(struct ata_probe_ent *ent);
extern int ata_scsi_detect(Scsi_Host_Template *sht); extern int ata_scsi_detect(Scsi_Host_Template *sht);
extern int ata_scsi_queuecmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
extern int ata_scsi_error(struct Scsi_Host *host); extern int ata_scsi_error(struct Scsi_Host *host);
extern int ata_scsi_release(struct Scsi_Host *host); extern int ata_scsi_release(struct Scsi_Host *host);
extern int ata_scsi_slave_config(struct scsi_device *sdev); extern int ata_scsi_slave_config(struct scsi_device *sdev);
...@@ -427,6 +427,9 @@ extern void ata_bmdma_start_pio (struct ata_queued_cmd *qc); ...@@ -427,6 +427,9 @@ extern void ata_bmdma_start_pio (struct ata_queued_cmd *qc);
extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits); extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat, unsigned int done_late); extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat, unsigned int done_late);
extern void ata_eng_timeout(struct ata_port *ap); extern void ata_eng_timeout(struct ata_port *ap);
extern int ata_std_bios_param(struct scsi_device *sdev,
struct block_device *bdev,
sector_t capacity, int geom[]);
static inline unsigned long msecs_to_jiffies(unsigned long msecs) static inline unsigned long msecs_to_jiffies(unsigned long msecs)
......
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