Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c	(revision b94334fffc8e58adb969bac1f1a860eace3290af)
+++ uspace/srv/bd/ata_bd/ata_bd.c	(revision a99cf073e9a8e1481a02b6120032ce29fd736ea1)
@@ -88,4 +88,5 @@
 static int disk_init(disk_t *d, int disk_id);
 static int drive_identify(int drive_id, void *buf);
+static void disk_print_summary(disk_t *d);
 static int wait_status(unsigned set, unsigned n_reset, uint8_t *pstatus,
     unsigned timeout);
@@ -111,7 +112,5 @@
 
 		if (rc == EOK) {
-			printf("%s: %u cylinders, %u heads, %u sectors.\n",
-			    disk[i].model, disk[i].cylinders, disk[i].heads,
-			    disk[i].sectors);
+			disk_print_summary(&disk[i]);
 		} else {
 			printf("Not found.\n");
@@ -150,4 +149,18 @@
 }
 
+/** Print one-line device summary. */
+static void disk_print_summary(disk_t *d)
+{
+	printf("%s: ", d->model);
+
+	if (d->amode == am_chs) {
+		printf("CHS %u cylinders, %u heads, %u sectors",
+		    disk->geom.cylinders, disk->geom.heads, disk->geom.sectors);
+	} else {
+		printf("LBA-28");
+	}
+
+	printf(" %llu blocks.\n", d->blocks);
+}
 
 /** Register driver and enable device I/O. */
@@ -275,9 +288,25 @@
 	}
 
-	d->cylinders = idata.cylinders;
-	d->heads = idata.heads;
-	d->sectors = idata.sectors;
-
-	d->blocks = d->cylinders * d->heads * d->sectors;
+	if ((idata.caps & cap_lba) == 0) {
+		/* Device only supports CHS addressing. */
+		d->amode = am_chs;
+
+		d->geom.cylinders = idata.cylinders;
+		d->geom.heads = idata.heads;
+		d->geom.sectors = idata.sectors;
+
+		d->blocks = d->geom.cylinders * d->geom.heads * d->geom.sectors;
+	} else {
+		/* Device supports LBA-28. */
+		d->amode = am_lba28;
+
+		d->geom.cylinders = 0;
+		d->geom.heads = 0;
+		d->geom.sectors = 0;
+
+		d->blocks =
+		    (uint32_t) idata.total_lba_sec0 | 
+		    ((uint32_t) idata.total_lba_sec1 << 16);
+	}
 
 	/*
@@ -425,14 +454,22 @@
 		return EINVAL;
 
-	/* Compute CHS. */
-	c = blk_idx / (d->heads * d->sectors);
-	idx = blk_idx % (d->heads * d->sectors);
-
-	h = idx / d->sectors;
-	s = 1 + (idx % d->sectors);
+	if (d->amode == am_chs) {
+		/* Compute CHS coordinates. */
+		c = blk_idx / (d->geom.heads * d->geom.sectors);
+		idx = blk_idx % (d->geom.heads * d->geom.sectors);
+
+		h = idx / d->geom.sectors;
+		s = 1 + (idx % d->geom.sectors);
+	} else {
+		/* Compute LBA-28 coordinates. */
+		s = blk_idx & 0xff;		/* bits 0-7 */
+		c = (blk_idx >> 8) & 0xffff;	/* bits 8-23 */
+		h = (blk_idx >> 24) & 0x0f;	/* bits 24-27 */
+	}
 
 	/* New value for Drive/Head register */
 	drv_head =
 	    ((disk_id != 0) ? DHR_DRV : 0) |
+	    ((d->amode != am_chs) ? DHR_LBA : 0) |
 	    (h & 0x0f);
 
@@ -506,14 +543,22 @@
 		return EINVAL;
 
-	/* Compute CHS. */
-	c = blk_idx / (d->heads * d->sectors);
-	idx = blk_idx % (d->heads * d->sectors);
-
-	h = idx / d->sectors;
-	s = 1 + (idx % d->sectors);
+	if (d->amode == am_chs) {
+		/* Compute CHS coordinates. */
+		c = blk_idx / (d->geom.heads * d->geom.sectors);
+		idx = blk_idx % (d->geom.heads * d->geom.sectors);
+
+		h = idx / d->geom.sectors;
+		s = 1 + (idx % d->geom.sectors);
+	} else {
+		/* Compute LBA-28 coordinates. */
+		s = blk_idx & 0xff;		/* bits 0-7 */
+		c = (blk_idx >> 8) & 0xffff;	/* bits 8-23 */
+		h = (blk_idx >> 24) & 0x0f;	/* bits 24-27 */
+	}
 
 	/* New value for Drive/Head register */
 	drv_head =
 	    ((disk_id != 0) ? DHR_DRV : 0) |
+	    ((d->amode != am_chs) ? DHR_LBA : 0) |
 	    (h & 0x0f);
 
Index: uspace/srv/bd/ata_bd/ata_bd.h
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.h	(revision b94334fffc8e58adb969bac1f1a860eace3290af)
+++ uspace/srv/bd/ata_bd/ata_bd.h	(revision a99cf073e9a8e1481a02b6120032ce29fd736ea1)
@@ -116,5 +116,6 @@
 
 enum drive_head_bits {
-	DHR_DRV		= 0x10
+	DHR_LBA		= 0x40,	/**< Use LBA addressing mode */
+	DHR_DRV		= 0x10	/**< Select device 1 */
 };
 
@@ -190,9 +191,30 @@
 } identify_data_t;
 
+enum ata_caps {
+	cap_iordy	= 0x0800,
+	cap_iordy_cbd	= 0x0400,
+	cap_lba		= 0x0200,
+	cap_dma		= 0x0100
+};
+
+/** Block addressing mode. */
+enum addr_mode {
+	am_chs,
+	am_lba28
+};
+
 typedef struct {
 	bool present;
-	unsigned heads;
-	unsigned cylinders;
-	unsigned sectors;
+	enum addr_mode amode;
+
+	/*
+	 * Geometry. Only valid if operating in CHS mode.
+	 */
+	struct {
+		unsigned heads;
+		unsigned cylinders;
+		unsigned sectors;
+	} geom;
+
 	uint64_t blocks;
 
