示例#1
0
static uint64_t ata_id_n_sectors(uint16_t *id)
{
	if (ata_id_has_lba(id)) {
		if (ata_id_has_lba48(id))
			return ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
		else
			return ata_id_u32(id, ATA_ID_LBA_CAPACITY);
	}

	return 0;
}
示例#2
0
static void bfin_ata_identify(struct ata_port *ap, int dev)
{
	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
	u8 status = 0;
	static u16 iobuf[ATA_SECTOR_WORDS];
	u64 n_sectors = 0;
	hd_driveid_t *iop = (hd_driveid_t *)iobuf;

	memset(iobuf, 0, sizeof(iobuf));

	if (!(ap->dev_mask & (1 << dev)))
		return;

	debug("port=%d dev=%d\n", ap->port_no, dev);

	bfin_dev_select(ap, dev);

	status = 0;
	/* Device Identify Command */
	write_atapi_register(base, ATA_REG_CMD, ATA_CMD_ID_ATA);
	bfin_check_altstatus(ap);
	udelay(10);

	status = bfin_ata_busy_wait(ap, ATA_BUSY, 1000, 0);
	if (status & ATA_ERR) {
		printf("\ndevice not responding\n");
		ap->dev_mask &= ~(1 << dev);
		return;
	}

	read_atapi_data(base, ATA_SECTOR_WORDS, iobuf);

	ata_swap_buf_le16(iobuf, ATA_SECTOR_WORDS);

	/* we require LBA and DMA support (bits 8 & 9 of word 49) */
	if (!ata_id_has_dma(iobuf) || !ata_id_has_lba(iobuf))
		printf("ata%u: no dma/lba\n", ap->port_no);

#ifdef DEBUG
	ata_dump_id(iobuf);
#endif

	n_sectors = ata_id_n_sectors(iobuf);

	if (n_sectors == 0) {
		ap->dev_mask &= ~(1 << dev);
		return;
	}

	ata_id_c_string(iobuf, (unsigned char *)sata_dev_desc[ap->port_no].revision,
			 ATA_ID_FW_REV, sizeof(sata_dev_desc[ap->port_no].revision));
	ata_id_c_string(iobuf, (unsigned char *)sata_dev_desc[ap->port_no].vendor,
			 ATA_ID_PROD, sizeof(sata_dev_desc[ap->port_no].vendor));
	ata_id_c_string(iobuf, (unsigned char *)sata_dev_desc[ap->port_no].product,
			 ATA_ID_SERNO, sizeof(sata_dev_desc[ap->port_no].product));

	if ((iop->config & 0x0080) == 0x0080)
		sata_dev_desc[ap->port_no].removable = 1;
	else
		sata_dev_desc[ap->port_no].removable = 0;

	sata_dev_desc[ap->port_no].lba = (u32) n_sectors;
	debug("lba=0x%lx\n", sata_dev_desc[ap->port_no].lba);

#ifdef CONFIG_LBA48
	if (iop->command_set_2 & 0x0400)
		sata_dev_desc[ap->port_no].lba48 = 1;
	else
		sata_dev_desc[ap->port_no].lba48 = 0;
#endif

	/* assuming HD */
	sata_dev_desc[ap->port_no].type = DEV_TYPE_HARDDISK;
	sata_dev_desc[ap->port_no].blksz = ATA_SECT_SIZE;
	sata_dev_desc[ap->port_no].lun = 0;	/* just to fill something in... */

	printf("PATA device#%d %s is found on ata port#%d.\n",
		ap->port_no%PATA_DEV_NUM_PER_PORT,
		sata_dev_desc[ap->port_no].vendor,
		ap->port_no/PATA_DEV_NUM_PER_PORT);
}
示例#3
0
int pio_write_buffer(struct ata_device *dev, struct ata_port *ap, unsigned long sector,
		     const u8* buf, unsigned int size, u32 *csum) {
	int ret;
	int writtensects=0;
	int i;
	u32 checksum = 0, carry = 0;
	const u16 *id = dev->id;
	unsigned long flags;

	spin_lock_irqsave(ap->lock, flags);
	
	while(size > 0) {
		/* Written according to ATA - 6 specification */
		int cnt=0;
		if (ata_id_has_lba48(id)) {
			/* LBA 48 addressing */
			lba48_address_write(ap, sector);
		} else if (ata_id_has_lba(id)) {
			/* LBA 28 addressing */
			lba28_address_write(ap, sector);
		} else {
			printk("ATA Dead System doesn't do CHS\n");
			spin_unlock_irqrestore(ap->lock, flags);
			return -ENODEV;
		}

		udelay(1);

		if((ret = pio_busy_wait(ap, 100000)) < 0) {
			spin_unlock_irqrestore(ap->lock, flags);			
			return ret;
		}

		for(i=(512/2);i;i--) { 
			u16 data;
			/* Unaligned access unwise, makes for funky code */
			if(size >= 2) {
				data = *buf++;
				data |= (*buf++)<<8;
				size -= 2;
			} else if (size == 1){
				data = *buf++;
				size = 0;
			} else {
				data = 0;
			}
			
			writew(data, (void __iomem *)ap->ioaddr.data_addr);
			checksum += carry;
			checksum += data;
			carry = (data > checksum);
			cnt++;
		}
		mdelay(5);

		if((ret = pio_wait(ap)) < 0) {
			spin_unlock_irqrestore(ap->lock, flags);						
			return ret;
		}

		sector++;
		writtensects++;
	}

	spin_unlock_irqrestore(ap->lock, flags);			
	
	checksum += carry;
	
	if(csum != NULL) {
		*csum += checksum;
		if(checksum > *csum)
			*csum = (*csum) + 1;
	}
	
	return writtensects;
}