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; }
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); }
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; }