Add support for the JMicron JMB360 SATAII controller.

Thanks to JMicron for providing needed info.

HW donated by:	Ralf Folkerts
This commit is contained in:
sos 2006-01-25 23:07:42 +00:00
parent 64e71c4974
commit 0d5c93667a
3 changed files with 119 additions and 24 deletions

View File

@ -99,6 +99,7 @@ static int ata_intel_31244_command(struct ata_request *request);
static void ata_intel_31244_reset(device_t dev);
static int ata_ite_chipinit(device_t dev);
static void ata_ite_setmode(device_t dev, int mode);
static int ata_jmicron_chipinit(device_t dev);
static int ata_marvell_chipinit(device_t dev);
static int ata_marvell_allocate(device_t dev);
static int ata_marvell_status(device_t dev);
@ -236,7 +237,9 @@ ata_sata_phy_enable(struct ata_channel *ch)
}
ata_udelay(5000);
for (loop = 0; loop < 10; loop++) {
ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_IDLE);
ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_IDLE |
ATA_SC_IPM_DIS_PARTIAL |
ATA_SC_IPM_DIS_SLUMBER);
ata_udelay(100);
if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == 0) {
ata_sata_connect(ch);
@ -448,28 +451,29 @@ ata_ahci_status(device_t dev)
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
struct ata_connect_task *tp;
u_int32_t action, status, error, issued;
u_int32_t action, istatus, sstatus, error, issued;
int offset = (ch->unit << 7);
int tag = 0;
action = ATA_INL(ctlr->r_res2, ATA_AHCI_IS) & (1 << ch->unit);
if (action) {
error = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SERR + offset);
status = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset);
if ((action = ATA_INL(ctlr->r_res2, ATA_AHCI_IS)) & (1 << ch->unit)) {
istatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset);
issued = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset);
sstatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SSTS + offset);
error = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SERR + offset);
/* clear interrupt(s) */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, action);
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, istatus);
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_SERR + offset, error);
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, status);
/* do we have cold connect surprise */
if (status & ATA_AHCI_P_IX_CPD) {
printf("ata_ahci_intr status=%08x error=%08x issued=%08x\n",
status, error, issued);
if (istatus & ATA_AHCI_P_IX_CPD) {
printf("ata_ahci_intr status=%08x sstatus=%08x error=%08x\n",
istatus, sstatus, error);
}
/* check for and handle connect events */
if (((status & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC)) ==
ATA_AHCI_P_IX_PC) &&
if ((istatus & ATA_AHCI_P_IX_PC) &&
(tp = (struct ata_connect_task *)
malloc(sizeof(struct ata_connect_task),
M_ATA, M_NOWAIT | M_ZERO))) {
@ -483,8 +487,9 @@ ata_ahci_status(device_t dev)
}
/* check for and handle disconnect events */
if (((status & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC)) ==
ATA_AHCI_P_IX_PRC) &&
else if ((istatus & ATA_AHCI_P_IX_PRC) &&
!((sstatus & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 ||
(sstatus & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2) &&
(tp = (struct ata_connect_task *)
malloc(sizeof(struct ata_connect_task),
M_ATA, M_NOWAIT | M_ZERO))) {
@ -497,9 +502,6 @@ ata_ahci_status(device_t dev)
taskqueue_enqueue(taskqueue_thread, &tp->task);
}
/* clear interrupt */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, action);
/* do we have any device action ? */
if (!(issued & (1 << tag)))
return 1;
@ -902,11 +904,13 @@ ata_ali_chipinit(device_t dev)
switch (ctlr->chip->cfg2) {
case ALISATA:
pci_write_config(dev, PCIR_COMMAND,
pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2);
ctlr->channels = ctlr->chip->cfg1;
ctlr->allocate = ata_ali_sata_allocate;
ctlr->setmode = ata_sata_setmode;
/* enable PCI interrupt */
pci_write_config(dev, PCIR_COMMAND,
pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2);
break;
case ALINEW:
@ -2039,6 +2043,84 @@ ata_ite_setmode(device_t dev, int mode)
}
/*
* JMicron chipset support functions
*/
int
ata_jmicron_ident(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
struct ata_chip_id *idx;
static struct ata_chip_id ids[] =
{{ ATA_JMB360, 0, 0, 0, ATA_SA300, "JMB360" },
{ 0, 0, 0, 0, 0, 0}};
char buffer[64];
if (!(idx = ata_match_chip(dev, ids)))
return ENXIO;
sprintf(buffer, "JMicron %s %s controller",
idx->text, ata_mode2str(idx->max_dma));
device_set_desc_copy(dev, buffer);
ctlr->chip = idx;
ctlr->chipinit = ata_jmicron_chipinit;
return 0;
}
static int
ata_jmicron_chipinit(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
if (ata_setup_interrupt(dev))
return ENXIO;
ctlr->r_type2 = SYS_RES_MEMORY;
ctlr->r_rid2 = PCIR_BAR(5);
if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
&ctlr->r_rid2, RF_ACTIVE)))
return ENXIO;
/* enable AHCI mode */
pci_write_config(dev, 0x41, 0xa1, 1);
/* reset AHCI controller */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC,
ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_HR);
DELAY(1000000);
if (ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & ATA_AHCI_GHC_HR) {
bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2);
device_printf(dev, "AHCI controller reset failure\n");
return ENXIO;
}
/* enable AHCI mode */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC,
ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_AE);
/* get the number of HW channels */
ctlr->channels = (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) +1;
ctlr->allocate = ata_ahci_allocate;
ctlr->reset = ata_ahci_reset;
ctlr->dmainit = ata_ahci_dmainit;
ctlr->setmode = ata_sata_setmode;
/* clear interrupts */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, ATA_INL(ctlr->r_res2, ATA_AHCI_IS));
/* enable AHCI interrupts */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC,
ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_IE);
/* enable PCI interrupt */
pci_write_config(dev, PCIR_COMMAND,
pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2);
return 0;
}
/*
* Marvell chipset support functions
*/
@ -2128,6 +2210,7 @@ ata_marvell_chipinit(device_t dev)
ATA_OUTL(ctlr->r_res1, 0x01d64, 0x000000ff/*HC0*/ | 0x0001fe00/*HC1*/ |
/*(1<<19) | (1<<20) | (1<<21) |*/(1<<22) | (1<<24) | (0x7f << 25));
/* enable PCI interrupt */
pci_write_config(dev, PCIR_COMMAND,
pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2);
return 0;
@ -4282,10 +4365,12 @@ ata_sis_chipinit(device_t dev)
ctlr->r_rid2 = PCIR_BAR(5);
if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
&ctlr->r_rid2, RF_ACTIVE))) {
pci_write_config(dev, PCIR_COMMAND,
pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400,2);
ctlr->allocate = ata_sis_allocate;
ctlr->reset = ata_sis_reset;
/* enable PCI interrupt */
pci_write_config(dev, PCIR_COMMAND,
pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400,2);
}
ctlr->setmode = ata_sata_setmode;
return 0;
@ -4471,10 +4556,12 @@ ata_via_chipinit(device_t dev)
ctlr->r_rid2 = PCIR_BAR(5);
if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
&ctlr->r_rid2, RF_ACTIVE))) {
pci_write_config(dev, PCIR_COMMAND,
pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400,2);
ctlr->allocate = ata_via_allocate;
ctlr->reset = ata_via_reset;
/* enable PCI interrupt */
pci_write_config(dev, PCIR_COMMAND,
pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400,2);
}
ctlr->setmode = ata_sata_setmode;
return 0;

View File

@ -113,6 +113,10 @@ ata_pci_probe(device_t dev)
if (!ata_ite_ident(dev))
return ATA_PROBE_OK;
break;
case ATA_JMICRON_ID:
if (!ata_jmicron_ident(dev))
return ATA_PROBE_OK;
break;
case ATA_MARVELL_ID:
if (!ata_marvell_ident(dev))
return ATA_PROBE_OK;

View File

@ -159,6 +159,9 @@ struct ata_connect_task {
#define ATA_IT8211F 0x82111283
#define ATA_IT8212F 0x82121283
#define ATA_JMICRON_ID 0x197b
#define ATA_JMB360 0x2360197b
#define ATA_MARVELL_ID 0x11ab
#define ATA_M88SX5040 0x504011ab
#define ATA_M88SX5041 0x504111ab
@ -411,6 +414,7 @@ int ata_cypress_ident(device_t);
int ata_highpoint_ident(device_t);
int ata_intel_ident(device_t);
int ata_ite_ident(device_t);
int ata_jmicron_ident(device_t);
int ata_marvell_ident(device_t);
int ata_national_ident(device_t);
int ata_nvidia_ident(device_t);