Ejemplo n.º 1
0
static int
ata_nvidia_chipinit(device_t dev)
{
    struct ata_pci_controller *ctlr = device_get_softc(dev);

    if (ata_setup_interrupt(dev, ata_generic_intr))
	return ENXIO;

    if (ctlr->chip->cfg1 & NVAHCI) {
	ctlr->ch_attach = ata_nvidia_ch_attach_dumb;
	ctlr->setmode = ata_sata_setmode;
    } else if (ctlr->chip->max_dma >= ATA_SA150) {
	if (pci_read_config(dev, PCIR_BAR(5), 1) & 1)
	    ctlr->r_type2 = SYS_RES_IOPORT;
	else
	    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))) {
	    int offset = ctlr->chip->cfg1 & NV4 ? 0x0440 : 0x0010;

	    ctlr->ch_attach = ata_nvidia_ch_attach;
	    ctlr->ch_detach = ata_pci_ch_detach;
	    ctlr->reset = ata_nvidia_reset;

	    /* enable control access */
	    pci_write_config(dev, 0x50, pci_read_config(dev, 0x50, 1) | 0x04,1);
	    /* MCP55 seems to need some time to allow r_res2 read. */
	    DELAY(10);
	    if (ctlr->chip->cfg1 & NVQ) {
		/* clear interrupt status */
		ATA_OUTL(ctlr->r_res2, offset, 0x00ff00ff);

		/* enable device and PHY state change interrupts */
		ATA_OUTL(ctlr->r_res2, offset + 4, 0x000d000d);

		/* disable NCQ support */
		ATA_OUTL(ctlr->r_res2, 0x0400,
			 ATA_INL(ctlr->r_res2, 0x0400) & 0xfffffff9);
	    } 
	    else {
		/* clear interrupt status */
		ATA_OUTB(ctlr->r_res2, offset, 0xff);

		/* enable device and PHY state change interrupts */
		ATA_OUTB(ctlr->r_res2, offset + 1, 0xdd);
	    }
	}
	ctlr->setmode = ata_sata_setmode;
	ctlr->getrev = ata_sata_getrev;
    }
    else {
	/* disable prefetch, postwrite */
	pci_write_config(dev, 0x51, pci_read_config(dev, 0x51, 1) & 0x0f, 1);
	ctlr->setmode = ata_nvidia_setmode;
    }
    return 0;
}
Ejemplo n.º 2
0
static int 
ata_nvidia_status(device_t dev)
{
    struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
    struct ata_channel *ch = device_get_softc(dev);
    int offset = ctlr->chip->cfg1 & NV4 ? 0x0440 : 0x0010;
    int shift = ch->unit << (ctlr->chip->cfg1 & NVQ ? 4 : 2);
    u_int32_t istatus;

    /* get interrupt status */
    if (ctlr->chip->cfg1 & NVQ)
	istatus = ATA_INL(ctlr->r_res2, offset);
    else
	istatus = ATA_INB(ctlr->r_res2, offset);

    /* do we have any PHY events ? */
    if (istatus & (0x0c << shift))
	ata_sata_phy_check_events(dev, -1);

    /* clear interrupt(s) */
    if (ctlr->chip->cfg1 & NVQ)
	ATA_OUTL(ctlr->r_res2, offset, (0x0f << shift) | 0x00f000f0);
    else
	ATA_OUTB(ctlr->r_res2, offset, (0x0f << shift));

    /* do we have any device action ? */
    return (istatus & (0x01 << shift));
}
Ejemplo n.º 3
0
int
ata_wait(struct ata_device *atadev, u_int8_t mask)
{
    int timeout = 0;
    
    DELAY(1);
    while (timeout < 5000000) { /* timeout 5 secs */
	atadev->channel->status = ATA_INB(atadev->channel->r_io, ATA_STATUS);

	/* if drive fails status, reselect the drive just to be sure */
	if (atadev->channel->status == 0xff) {
	    ata_prtdev(atadev, "no status, reselecting device\n");
	    ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM|atadev->unit);
	    DELAY(10);
	    atadev->channel->status = ATA_INB(atadev->channel->r_io,ATA_STATUS);
	    if (atadev->channel->status == 0xff)
		return -1;
	}

	/* are we done ? */
	if (!(atadev->channel->status & ATA_S_BUSY))
	    break;	      

	if (timeout > 1000) {
	    timeout += 1000;
	    DELAY(1000);
	}
	else {
	    timeout += 10;
	    DELAY(10);
	}
    }	 
    if (atadev->channel->status & ATA_S_ERROR)
	atadev->channel->error = ATA_INB(atadev->channel->r_io, ATA_ERROR);
    if (timeout >= 5000000)	 
	return -1;	    
    if (!mask)	   
	return (atadev->channel->status & ATA_S_ERROR);	 
    
    /* Wait 50 msec for bits wanted. */	   
    timeout = 5000;
    while (timeout--) {	  
	atadev->channel->status = ATA_INB(atadev->channel->r_io, ATA_STATUS);
	if ((atadev->channel->status & mask) == mask) {
	    if (atadev->channel->status & ATA_S_ERROR)
		atadev->channel->error=ATA_INB(atadev->channel->r_io,ATA_ERROR);
	    return (atadev->channel->status & ATA_S_ERROR);	      
	}
	DELAY (10);	   
    }	  
    return -1;	    
}   
Ejemplo n.º 4
0
static int
ata_cbuschannel_banking(device_t dev, int flags)
{
    struct ata_cbus_controller *ctlr = device_get_softc(device_get_parent(dev));
    struct ata_channel *ch = device_get_softc(dev);
    int res;

    mtx_lock(&ctlr->bank_mtx);
    switch (flags) {
    case ATA_LF_LOCK:
	if (ctlr->locked_bank == -1)
	    ctlr->locked_bank = ch->unit;
	if (ctlr->locked_bank == ch->unit) {
	    ctlr->hardware_bank = ch->unit;
	    ATA_OUTB(ctlr->bankio, 0, ch->unit);
	}
	else
	    ctlr->restart_bank = ch->unit;
	break;

    case ATA_LF_UNLOCK:
	if (ctlr->locked_bank == ch->unit) {
	    ctlr->locked_bank = -1;
	    if (ctlr->restart_bank != -1) {
		if ((ch = ctlr->interrupt[ctlr->restart_bank].argument)) {
		    ctlr->restart_bank = -1;
		    mtx_unlock(&ctlr->bank_mtx);
		    ata_start(ch->dev);
		    return -1;
		}
	    }
	}
	break;

    case ATA_LF_WHICH:
	break;
    }
    res = ctlr->locked_bank;
    mtx_unlock(&ctlr->bank_mtx);
    return res;
}
Ejemplo n.º 5
0
static int
ata_service(struct ata_channel *ch)
{
    /* do we have a SERVICE request from the drive ? */
    if ((ch->status & (ATA_S_SERVICE|ATA_S_ERROR|ATA_S_DRQ)) == ATA_S_SERVICE) {
	ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT,
		 ata_dmastatus(ch) | ATA_BMSTAT_INTERRUPT);
#if NATADISK > 0
	if ((ATA_INB(ch->r_io, ATA_DRIVE) & ATA_SLAVE) == ATA_MASTER) {
	    if ((ch->devices & ATA_ATA_MASTER) && ch->device[MASTER].driver)
		return ad_service((struct ad_softc *)
				  ch->device[MASTER].driver, 0);
	}
	else {
	    if ((ch->devices & ATA_ATA_SLAVE) && ch->device[SLAVE].driver)
		return ad_service((struct ad_softc *)
				  ch->device[SLAVE].driver, 0);
	}
#endif
    }
    return ATA_OP_FINISHED;
}
Ejemplo n.º 6
0
void
ata_reset(struct ata_channel *ch)
{
    u_int8_t lsb, msb, ostat0, ostat1;
    u_int8_t stat0 = 0, stat1 = 0;
    int mask = 0, timeout;

    /* do we have any signs of ATA/ATAPI HW being present ? */
    ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
    DELAY(10);
    ostat0 = ATA_INB(ch->r_io, ATA_STATUS);
    if ((ostat0 & 0xf8) != 0xf8 && ostat0 != 0xa5) {
	stat0 = ATA_S_BUSY;
	mask |= 0x01;
    }
    ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
    DELAY(10);	
    ostat1 = ATA_INB(ch->r_io, ATA_STATUS);
    if ((ostat1 & 0xf8) != 0xf8 && ostat1 != 0xa5) {
	stat1 = ATA_S_BUSY;
	mask |= 0x02;
    }

    ch->devices = 0;
    if (!mask)
	return;

    /* in some setups we dont want to test for a slave */
    if (ch->flags & ATA_NO_SLAVE) {
	stat1 = 0x0;
	mask &= ~0x02;
    }

    if (bootverbose)
	ata_printf(ch, -1, "mask=%02x ostat0=%02x ostat2=%02x\n",
		   mask, ostat0, ostat1);

    /* reset channel */
    ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
    DELAY(10);
    ATA_OUTB(ch->r_altio, ATA_ALTSTAT, ATA_A_IDS | ATA_A_RESET);
    DELAY(10000); 
    ATA_OUTB(ch->r_altio, ATA_ALTSTAT, ATA_A_IDS);
    DELAY(100000);
    ATA_INB(ch->r_io, ATA_ERROR);

    /* wait for BUSY to go inactive */
    for (timeout = 0; timeout < 310000; timeout++) {
	if (stat0 & ATA_S_BUSY) {
	    ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
	    DELAY(10);

	    /* check for ATAPI signature while its still there */
	    lsb = ATA_INB(ch->r_io, ATA_CYL_LSB);
	    msb = ATA_INB(ch->r_io, ATA_CYL_MSB);
	    stat0 = ATA_INB(ch->r_io, ATA_STATUS);
	    if (!(stat0 & ATA_S_BUSY)) {
		if (bootverbose)
		    ata_printf(ch, ATA_MASTER, "ATAPI %02x %02x\n", lsb, msb);
		if (lsb == ATAPI_MAGIC_LSB && msb == ATAPI_MAGIC_MSB)
		    ch->devices |= ATA_ATAPI_MASTER;
	    }
	}
	if (stat1 & ATA_S_BUSY) {
	    ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
	    DELAY(10);

	    /* check for ATAPI signature while its still there */
	    lsb = ATA_INB(ch->r_io, ATA_CYL_LSB);
	    msb = ATA_INB(ch->r_io, ATA_CYL_MSB);
	    stat1 = ATA_INB(ch->r_io, ATA_STATUS);
	    if (!(stat1 & ATA_S_BUSY)) {
		if (bootverbose)
		    ata_printf(ch, ATA_SLAVE, "ATAPI %02x %02x\n", lsb, msb);
		if (lsb == ATAPI_MAGIC_LSB && msb == ATAPI_MAGIC_MSB)
		    ch->devices |= ATA_ATAPI_SLAVE;
	    }
	}
	if (mask == 0x01)      /* wait for master only */
	    if (!(stat0 & ATA_S_BUSY))
		break;
	if (mask == 0x02)      /* wait for slave only */
	    if (!(stat1 & ATA_S_BUSY))
		break;
	if (mask == 0x03)      /* wait for both master & slave */
	    if (!(stat0 & ATA_S_BUSY) && !(stat1 & ATA_S_BUSY))
		break;
	DELAY(100);
    }	
    DELAY(10);
    ATA_OUTB(ch->r_altio, ATA_ALTSTAT, ATA_A_4BIT);

    if (stat0 & ATA_S_BUSY)
	mask &= ~0x01;
    if (stat1 & ATA_S_BUSY)
	mask &= ~0x02;
    if (bootverbose)
	ata_printf(ch, -1, "mask=%02x stat0=%02x stat1=%02x\n", 
		   mask, stat0, stat1);
    if (!mask)
	return;

    if (mask & 0x01 && ostat0 != 0x00 && !(ch->devices & ATA_ATAPI_MASTER)) {
	ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
	DELAY(10);
	ATA_OUTB(ch->r_io, ATA_ERROR, 0x58);
	ATA_OUTB(ch->r_io, ATA_CYL_LSB, 0xa5);
	lsb = ATA_INB(ch->r_io, ATA_ERROR);
	msb = ATA_INB(ch->r_io, ATA_CYL_LSB);
	if (bootverbose)
	    ata_printf(ch, ATA_MASTER, "ATA %02x %02x\n", lsb, msb);
	if (lsb != 0x58 && msb == 0xa5)
	    ch->devices |= ATA_ATA_MASTER;
    }
    if (mask & 0x02 && ostat1 != 0x00 && !(ch->devices & ATA_ATAPI_SLAVE)) {
	ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
	DELAY(10);
	ATA_OUTB(ch->r_io, ATA_ERROR, 0x58);
	ATA_OUTB(ch->r_io, ATA_CYL_LSB, 0xa5);
	lsb = ATA_INB(ch->r_io, ATA_ERROR);
	msb = ATA_INB(ch->r_io, ATA_CYL_LSB);
	if (bootverbose)
	    ata_printf(ch, ATA_SLAVE, "ATA %02x %02x\n", lsb, msb);
	if (lsb != 0x58 && msb == 0xa5)
	    ch->devices |= ATA_ATA_SLAVE;
    }
    if (bootverbose)
	ata_printf(ch, -1, "devices=%02x\n", ch->devices);
}
Ejemplo n.º 7
0
int
ata_command(struct ata_device *atadev, u_int8_t command,
	   u_int64_t lba, u_int16_t count, u_int8_t feature, int flags)
{
    int error = 0;
#ifdef ATA_DEBUG
    ata_prtdev(atadev, "ata_command: addr=%04lx, cmd=%02x, "
	       "lba=%lld, count=%d, feature=%d, flags=%02x\n",
	       rman_get_start(atadev->channel->r_io), 
	       command, lba, count, feature, flags);
#endif

    /* select device */
    ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit);

    /* disable interrupt from device */
    if (atadev->channel->flags & ATA_QUEUED)
	ATA_OUTB(atadev->channel->r_altio, ATA_ALTSTAT, ATA_A_IDS | ATA_A_4BIT);

    /* ready to issue command ? */
    if (ata_wait(atadev, 0) < 0) { 
	ata_prtdev(atadev, "timeout sending command=%02x s=%02x e=%02x\n",
		   command, atadev->channel->status, atadev->channel->error);
	return -1;
    }

    /* only use 48bit addressing if needed because of the overhead */
    if ((lba >= 268435455 || count > 256) && atadev->param &&
	atadev->param->support.address48) {
	ATA_OUTB(atadev->channel->r_io, ATA_FEATURE, (feature>>8) & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_FEATURE, feature);
	ATA_OUTB(atadev->channel->r_io, ATA_COUNT, (count>>8) & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_COUNT, count & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, (lba>>24) & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, lba & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_CYL_LSB, (lba>>32) & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_CYL_LSB, (lba>>8) & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_CYL_MSB, (lba>>40) & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_CYL_MSB, (lba>>16) & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_LBA | atadev->unit);

	/* translate command into 48bit version */
	switch (command) {
	case ATA_C_READ:
	    command = ATA_C_READ48; break;
	case ATA_C_READ_MUL:
	    command = ATA_C_READ_MUL48; break;
	case ATA_C_READ_DMA:
	    command = ATA_C_READ_DMA48; break;
	case ATA_C_READ_DMA_QUEUED:
	    command = ATA_C_READ_DMA_QUEUED48; break;
	case ATA_C_WRITE:
	    command = ATA_C_WRITE48; break;
	case ATA_C_WRITE_MUL:
	    command = ATA_C_WRITE_MUL48; break;
	case ATA_C_WRITE_DMA:
	    command = ATA_C_WRITE_DMA48; break;
	case ATA_C_WRITE_DMA_QUEUED:
	    command = ATA_C_WRITE_DMA_QUEUED48; break;
	case ATA_C_FLUSHCACHE:
	    command = ATA_C_FLUSHCACHE48; break;
	default:
	    ata_prtdev(atadev, "can't translate cmd to 48bit version\n");
	    return -1;
	}
    }