Request for new ATA feature

Peter Jeremy PeterJeremy at optushome.com.au
Sat Mar 5 04:34:49 PST 2005


On Sun, 2005-Feb-27 13:58:11 +1100, Peter Jeremy wrote:
>I have a suggestion for a feature that would be useful to me:  I am
>in the process of rejunenating an old system for use as a proxy server.
>Unfortunately, the BIOS is limited to 32GB and I want to put an 80GB
>drive in.  The drive (Seagate Barracuda) includes a jumper that makes
>the drive report a capacity of 32GB until it is reset using a "set
>features/report full capacity available" command.

Attached is a patch against 5.3-RELEASE to implement this.  It applies
cleanly to -CURRENT but I haven't tested it there.

-- 
Peter Jeremy
-------------- next part --------------
Index: sys/ata.h
===================================================================
RCS file: /usr/ncvs/src/sys/sys/ata.h,v
retrieving revision 1.23
diff -u -r1.23 ata.h
--- sys/ata.h	20 May 2004 15:09:41 -0000	1.23
+++ sys/ata.h	5 Mar 2005 10:52:27 -0000
@@ -251,6 +251,7 @@
 #define		ATA_SF_DIS_RELIRQ	0xdd	/* disable release interrupt */
 #define		ATA_SF_ENAB_SRVIRQ	0x5e	/* enable service interrupt */
 #define		ATA_SF_DIS_SRVIRQ	0xde	/* disable service interrupt */
+#define		ATA_SF_SEA_FULLCAP	0xf1	/* SGT Report Full Capacity */
 
 /* ATAPI commands */
 #define ATAPI_TEST_UNIT_READY		0x00	/* check if device is ready */
Index: dev/ata/ata-all.c
===================================================================
RCS file: /usr/ncvs/src/sys/dev/ata/ata-all.c,v
retrieving revision 1.222.2.4.2.1
diff -u -r1.222.2.4.2.1 ata-all.c
--- dev/ata/ata-all.c	24 Oct 2004 09:31:25 -0000	1.222.2.4.2.1
+++ dev/ata/ata-all.c	5 Mar 2005 10:45:30 -0000
@@ -68,7 +68,6 @@
 /* prototypes */
 static void ata_shutdown(void *, int);
 static void ata_interrupt(void *);
-static int ata_getparam(struct ata_device *, u_int8_t);
 static void ata_identify_devices(struct ata_channel *);
 static void ata_boot_attach(void);
 static void bswap(int8_t *, int);
@@ -638,7 +637,7 @@
 /*
  * device probe functions
  */
-static int
+int
 ata_getparam(struct ata_device *atadev, u_int8_t command)
 {
     struct ata_request *request;
Index: dev/ata/ata-all.h
===================================================================
RCS file: /usr/ncvs/src/sys/dev/ata/ata-all.h,v
retrieving revision 1.81.2.3
diff -u -r1.81.2.3 ata-all.h
--- dev/ata/ata-all.h	10 Oct 2004 15:01:47 -0000	1.81.2.3
+++ dev/ata/ata-all.h	5 Mar 2005 10:45:30 -0000
@@ -408,6 +408,7 @@
 int ata_wmode(struct ata_params *ap);
 int ata_umode(struct ata_params *ap);
 int ata_limit_mode(struct ata_device *atadev, int mode, int maxmode);
+int ata_getparam(struct ata_device *atadev, u_int8_t command);
 
 /* ata-queue.c: */
 int ata_reinit(struct ata_channel *ch);
Index: dev/ata/ata-commands.h
===================================================================
RCS file: /usr/ncvs/src/sys/dev/ata/ata-commands.h,v
retrieving revision 1.2
diff -u -r1.2 ata-commands.h
--- dev/ata/ata-commands.h	30 Apr 2004 16:21:34 -0000	1.2
+++ dev/ata/ata-commands.h	5 Mar 2005 10:45:30 -0000
@@ -69,6 +69,7 @@
 #define		ATA_SF_DIS_RELIRQ	0xdd	/* disable release interrupt */
 #define		ATA_SF_ENAB_SRVIRQ	0x5e	/* enable service interrupt */
 #define		ATA_SF_DIS_SRVIRQ	0xde	/* disable service interrupt */
+#define		ATA_SF_SEA_FULLCAP	0xf1	/* SGT Report Full Capacity */
 
 /* ATAPI commands */
 #define ATAPI_TEST_UNIT_READY		0x00	/* check if device is ready */
Index: dev/ata/ata-disk.c
===================================================================
RCS file: /usr/ncvs/src/sys/dev/ata/ata-disk.c,v
retrieving revision 1.175.2.2
diff -u -r1.175.2.2 ata-disk.c
--- dev/ata/ata-disk.c	30 Sep 2004 21:29:19 -0000	1.175.2.2
+++ dev/ata/ata-disk.c	5 Mar 2005 12:29:32 -0000
@@ -89,6 +89,24 @@
     adp->lun = ata_get_lun(&adp_lun_map);
 #endif
     ata_set_name(atadev, "ad", adp->lun);
+    /*
+     * If this looks like a Seagate drive running in limited capacity mode
+     * (reported capacity about 32GB), send an ATA Set Features "Report Full
+     * Capacity Available" command and redo the drive identification
+     */
+    if (!strncmp(atadev->param->model, "ST", 2) &&
+	atadev->param->lba_size_2 > 950 && atadev->param->lba_size_2 < 1025) {
+	if (bootverbose)
+	    ata_prtdev(atadev, "Initial geometry: %u sectors (%u/%u/%u)\n",
+		       (u_int32_t)atadev->param->lba_size_1 |
+		       ((u_int32_t)atadev->param->lba_size_2 << 16),
+		       atadev->param->cylinders, atadev->param->heads,
+		       atadev->param->sectors);
+	/* Reset the drive capacity */
+	ata_controlcmd(atadev, ATA_SETFEATURES, ATA_SF_SEA_FULLCAP, 0, 0);
+	/* Repeat drive identification */
+	ata_getparam(atadev, ATA_ATA_IDENTIFY);
+    }
     adp->heads = atadev->param->heads;
     adp->sectors = atadev->param->sectors;
     adp->total_secs = atadev->param->cylinders * adp->heads * adp->sectors;	


More information about the freebsd-current mailing list