int scan_sata(int port) { unsigned char serial[ATA_ID_SERNO_LEN + 1]; unsigned char firmware[ATA_ID_FW_REV_LEN + 1]; unsigned char product[ATA_ID_PROD_LEN + 1]; u64 n_sectors; u16 *id; struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; if (!priv->link) return -ENODEV; id = (u16 *)malloc(ATA_ID_WORDS * 2); if (!id) { printf("Failed to malloc id data\n"); return -ENOMEM; } mv_sata_identify(port, id); ata_swap_buf_le16(id, ATA_ID_WORDS); #ifdef DEBUG ata_dump_id(id); #endif /* Serial number */ ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial)); memcpy(sata_dev_desc[port].product, serial, sizeof(serial)); /* Firmware version */ ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware)); memcpy(sata_dev_desc[port].revision, firmware, sizeof(firmware)); /* Product model */ ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product)); memcpy(sata_dev_desc[port].vendor, product, sizeof(product)); /* Total sectors */ n_sectors = ata_id_n_sectors(id); sata_dev_desc[port].lba = n_sectors; /* Check if support LBA48 */ if (ata_id_has_lba48(id)) { sata_dev_desc[port].lba48 = 1; debug("Device support LBA48\n"); } /* Get the NCQ queue depth from device */ priv->queue_depth = ata_id_queue_depth(id); /* Get the xfer mode from device */ mv_sata_xfer_mode(port, id); /* Set the xfer mode to highest speed */ mv_sata_set_features(port); /* Start up */ mv_start_edma_engine(port); 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 scan_sata(int dev) { fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv; unsigned char serial[ATA_ID_SERNO_LEN + 1]; unsigned char firmware[ATA_ID_FW_REV_LEN + 1]; unsigned char product[ATA_ID_PROD_LEN + 1]; u16 *id; u64 n_sectors; /* if no detected link */ if (!sata->link) return -1; id = (u16 *)malloc(ATA_ID_WORDS * 2); if (!id) { printf("id malloc failed\n\r"); return -1; } /* Identify device to get information */ fsl_sata_identify(dev, id); /* Serial number */ ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial)); memcpy(sata_dev_desc[dev].product, serial, sizeof(serial)); /* Firmware version */ ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware)); memcpy(sata_dev_desc[dev].revision, firmware, sizeof(firmware)); /* Product model */ ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product)); memcpy(sata_dev_desc[dev].vendor, product, sizeof(product)); /* Totoal sectors */ n_sectors = ata_id_n_sectors(id); sata_dev_desc[dev].lba = (u32)n_sectors; /* Check if support LBA48 */ if (ata_id_has_lba48(id)) { sata_dev_desc[dev].lba48 = 1; debug("Device support LBA48\n\r"); } /* Get the NCQ queue depth from device */ sata->queue_depth = ata_id_queue_depth(id); /* Get the xfer mode from device */ fsl_sata_xfer_mode(dev, id); /* Get the write cache status from device */ fsl_sata_init_wcache(dev, id); /* Set the xfer mode to highest speed */ fsl_sata_set_features(dev); #ifdef DEBUG fsl_sata_identify(dev, id); ata_dump_id(id); #endif free((void *)id); return 0; }
static int ata_port_init(struct ata_port *port) { int rc; struct ata_port_operations *ops = port->ops; struct device_d *dev = &port->class_dev; if (ops->init) { rc = ops->init(port); if (rc) return rc; } port->id = dma_alloc(SECTOR_SIZE); port->blk.dev = dev; port->blk.ops = &ata_ops; if (ops->reset) { rc = ops->reset(port); if (rc) { dev_dbg(dev, "Resetting failed\n"); goto on_error; } } rc = ops->read_id(port, port->id); if (rc != 0) { dev_dbg(dev, "Reading ID failed\n"); goto on_error; } ata_fix_endianess(port->id, SECTOR_SIZE / sizeof(uint16_t)); rc = ata_id_is_valid(port->id); if (rc) { dev_err(dev, "ata id invalid\n"); free(port->id); return rc; } #ifdef DEBUG ata_dump_id(port->id); #endif rc = cdev_find_free_index("ata"); if (rc == -1) pr_err("Cannot find a free index for the disk node\n"); port->blk.num_blocks = ata_id_n_sectors(port->id); port->blk.cdev.name = asprintf("ata%d", rc); port->blk.blockbits = SECTOR_SHIFT; rc = blockdevice_register(&port->blk); if (rc != 0) { dev_err(dev, "Failed to register blockdevice\n"); goto on_error; } dev_info(dev, "registered /dev/%s\n", port->blk.cdev.name); /* create partitions on demand */ rc = parse_partition_table(&port->blk); if (rc != 0) dev_warn(dev, "No partition table found\n"); return 0; on_error: return rc; }
static void __maybe_unused ata_dump_id(uint16_t *id) { unsigned char serial[ATA_ID_SERNO_LEN + 1]; unsigned char firmware[ATA_ID_FW_REV_LEN + 1]; unsigned char product[ATA_ID_PROD_LEN + 1]; uint64_t n_sectors; /* Serial number */ ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial)); printf("S/N: %s\n\r", serial); /* Firmware version */ ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware)); printf("Firmware version: %s\n\r", firmware); /* Product model */ ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product)); printf("Product model number: %s\n\r", product); /* Total sectors of device */ n_sectors = ata_id_n_sectors(id); printf("Capablity: %lld sectors\n\r", n_sectors); printf ("id[49]: capabilities = 0x%04x\n" "id[53]: field valid = 0x%04x\n" "id[63]: mwdma = 0x%04x\n" "id[64]: pio = 0x%04x\n" "id[75]: queue depth = 0x%04x\n", id[ATA_ID_CAPABILITY], id[ATA_ID_FIELD_VALID], id[ATA_ID_MWDMA_MODES], id[ATA_ID_PIO_MODES], id[ATA_ID_QUEUE_DEPTH]); printf ("id[76]: sata capablity = 0x%04x\n" "id[78]: sata features supported = 0x%04x\n" "id[79]: sata features enable = 0x%04x\n", id[76], /* FIXME */ id[78], /* FIXME */ id[79]); /* FIXME */ printf ("id[80]: major version = 0x%04x\n" "id[81]: minor version = 0x%04x\n" "id[82]: command set supported 1 = 0x%04x\n" "id[83]: command set supported 2 = 0x%04x\n" "id[84]: command set extension = 0x%04x\n", id[ATA_ID_MAJOR_VER], id[81], /* FIXME */ id[ATA_ID_COMMAND_SET_1], id[ATA_ID_COMMAND_SET_2], id[ATA_ID_CFSSE]); printf ("id[85]: command set enable 1 = 0x%04x\n" "id[86]: command set enable 2 = 0x%04x\n" "id[87]: command set default = 0x%04x\n" "id[88]: udma = 0x%04x\n" "id[93]: hardware reset result = 0x%04x\n", id[ATA_ID_CFS_ENABLE_1], id[ATA_ID_CFS_ENABLE_2], id[ATA_ID_CSF_DEFAULT], id[ATA_ID_UDMA_MODES], id[ATA_ID_HW_CONFIG]); }