{"id":27,"date":"2012-04-11T19:10:54","date_gmt":"2012-04-11T11:10:54","guid":{"rendered":"http:\/\/www.datarelab.com\/blog\/?p=27"},"modified":"2012-04-11T19:10:54","modified_gmt":"2012-04-11T11:10:54","slug":"%e8%a7%a3%e9%99%a4%e7%a1%ac%e7%9b%98hpa%20--%20setmax.c","status":"publish","type":"post","link":"https:\/\/www.datarelab.com\/blog\/Technical_literature\/27.html","title":{"rendered":"\u89e3\u9664\u786c\u76d8HPA -- setmax.c"},"content":{"rendered":"<pre class=\"brush:cpp; toolbar: true; auto-links: true;\">\/* setmax.c - aeb, 000326 - use on 2.4.0test9 or newer *\/\r\n\/* IBM part thanks to Matan Ziv-Av &lt;matan@svgalib.org&gt; *\/\r\n\/*\r\n * Results on Maxtor disks:\r\n * The jumper that clips capacity does not influence the value returned\r\n * by READ_NATIVE_MAX_ADDRESS, so it is possible to set the jumper\r\n * and let the kernel, or a utility (like this one) run at boot time\r\n * restore full capacity.\r\n * For example, run \"setmax -d 0 \/dev\/hdX\" for suitable X.\r\n * Kernel patches exist that do the same.\r\n *\r\n * Results on IBM disks:\r\n * The jumper that clips capacity is ruthless. You clipped capacity.\r\n * However, if your BIOS hangs on a large disk, do not use the jumper\r\n * but find another machine and use a utility (like this one) to\r\n * clip the non-volatile max address.\r\n * For example, run \"setmax -m 66055248 \/dev\/hdX\" for suitable X.\r\n * Now go back to your first machine and proceed as with Maxtor drives above.\r\n *\/\r\n#include &lt;stdio.h&gt;\r\n#include &lt;fcntl.h&gt;\r\n#include &lt;getopt.h&gt;\r\n#include &lt;linux\/hdreg.h&gt;\r\n\r\n#ifndef HDIO_DRIVE_CMD_AEB\r\n#define HDIO_DRIVE_CMD_AEB\t0x031e\r\n#endif\r\n\r\n#define INITIALIZE_DRIVE_PARAMETERS 0x91\r\n#define READ_NATIVE_MAX_ADDRESS 0xf8\r\n#define CHECK_POWER_MODE\t0xe5\r\n#define SET_MAX\t\t\t0xf9\r\n\r\n#define LBA\t0x40\r\n#define VV\t1\t\t\/* if set in sectorct then NOT volatile *\/\r\n\r\nstruct idecmdin {\r\n\tunsigned char cmd;\r\n\tunsigned char feature;\r\n\tunsigned char nsect;\r\n\tunsigned char sect, lcyl, hcyl;\r\n\tunsigned char select;\r\n};\r\n\r\nstruct idecmdout {\r\n\tunsigned char status;\r\n\tunsigned char error;\r\n\tunsigned char nsect;\r\n\tunsigned char sect, lcyl, hcyl;\r\n\tunsigned char select;\r\n};\r\n\r\nunsigned int\r\ntolba(unsigned char *args) {\r\n\treturn ((args[6] &amp; 0xf) &lt;&lt; 24) + (args[5] &lt;&lt; 16) + (args[4] &lt;&lt; 8) + args[3];\r\n}\r\n\r\nvoid\r\nfromlba(unsigned char *args, unsigned int lba) {\r\n\targs[3] = (lba &amp; 0xff);\r\n\tlba &gt;&gt;= 8;\r\n\targs[4] = (lba &amp; 0xff);\r\n\tlba &gt;&gt;= 8;\r\n\targs[5] = (lba &amp; 0xff);\r\n\tlba &gt;&gt;= 8;\r\n\targs[6] = (args[6] &amp; 0xf0) | (lba &amp; 0xf);\r\n}\r\n\r\nint\r\nget_identity(int fd) {\r\n\tunsigned char args[4+512] = {WIN_IDENTIFY,0,0,1,};\r\n\tstruct hd_driveid *id = (struct hd_driveid *)&amp;args[4];\r\n\r\n\tif (ioctl(fd, HDIO_DRIVE_CMD, &amp;args)) {\r\n\t\tperror(\"HDIO_DRIVE_CMD\");\r\n\t\tfprintf(stderr,\r\n\t\t\t\"WIN_IDENTIFY failed - trying WIN_PIDENTIFY\\n\");\r\n\t\targs[0] = WIN_PIDENTIFY;\r\n\t\tif (ioctl(fd, HDIO_DRIVE_CMD, &amp;args)) {\r\n\t\t\tperror(\"HDIO_DRIVE_CMD\");\r\n\t\t\tfprintf(stderr,\r\n\t\t\t       \"WIN_PIDENTIFY also failed - giving up\\n\");\r\n\t\t\texit(1);\r\n\t\t}\r\n\t}\r\n\r\n\tprintf(\"lba capacity: %d sectors (%lld bytes)\\n\",\r\n\t       id-&gt;lba_capacity,\r\n\t       (long long) id-&gt;lba_capacity * 512);\r\n}\r\n\r\n\/*\r\n * result: in LBA mode precisely what is expected\r\n *         in CHS mode the correct H and S, and C mod 65536.\r\n *\/\r\nunsigned int\r\nget_native_max(int fd, int slave) {\r\n\tunsigned char args[7];\r\n\tint i, max;\r\n\r\n\tfor (i=0; i&lt;7; i++)\r\n\t\targs[i] = 0;\r\n\targs[0] = READ_NATIVE_MAX_ADDRESS;\r\n\targs[6] = (slave ? 0x10 : 0) | LBA;\r\n\tif (ioctl(fd, HDIO_DRIVE_CMD_AEB, &amp;args)) {\r\n\t\tperror(\"HDIO_DRIVE_CMD_AEB failed READ_NATIVE_MAX_ADDRESS\");\r\n\t\tfor (i=0; i&lt;7; i++)\r\n\t\t\tprintf(\"%d = 0x%x\\n\", args[i], args[i]);\r\n\t\texit(1);\r\n\t}\r\n\treturn tolba(args);\r\n}\r\n\r\n\/*\r\n * SET_MAX_ADDRESS requires immediately preceding READ_NATIVE_MAX_ADDRESS\r\n *\r\n * On old Maxtor disk: this fails for delta &lt;= 254, succeeds for delta &gt;= 255.\r\n * (So, in order to get the last 255*512=130560 bytes back one has to reboot.\r\n * Side effect: reset to CurCHS=16383\/16\/63, CurSects=16514064.)\r\n * On new Maxtor disk: this works.\r\n * On IBM disk without jumper: this works.\r\n *\/\r\nvoid\r\nset_max_address(int fd, int slave, int delta, int max, int volat) {\r\n\tunsigned char args[7];\r\n\tint i, nativemax, newmax;\r\n\r\n\tnativemax = get_native_max(fd, slave);\r\n\tprintf(\"nativemax=%d (0x%x)\\n\", nativemax, nativemax);\r\n\r\n\tfor (i=0; i&lt;7; i++)\r\n\t\targs[i] = 0;\r\n\targs[0] = SET_MAX;\r\n\targs[1] = 0;\r\n\targs[2] = (volat ? 0 : 1);\r\n\tif (delta != -1)\r\n\t\tnewmax = nativemax-delta;\r\n\telse\r\n\t\tnewmax = max-1;\r\n\tfromlba(args, newmax);\r\n\targs[6] |= LBA;\r\n\r\n\tif (ioctl(fd, HDIO_DRIVE_CMD_AEB, &amp;args)) {\r\n\t\tperror(\"HDIO_DRIVE_CMD_AEB failed SET_MAX\");\r\n\t\tfor (i=0; i&lt;7; i++)\r\n\t\t\tprintf(\"%d = 0x%x\\n\", args[i], args[i]);\r\n\t\texit(1);\r\n\t}\r\n}\r\n\r\nstatic char short_opts[] = \"d:m:\";\r\nstatic const struct option long_opts[] = {\r\n\t{ \"delta\",\trequired_argument,\tNULL,\t'd' },\r\n\t{ \"max\",\trequired_argument,\tNULL,\t'm' },\r\n        { NULL, 0, NULL, 0 }\r\n};\r\n\r\nstatic char *usage_txt =\r\n\"Call: setmax [-d D] [-m M] DEVICE\\n\"\r\n\"\\n\"\r\n\"The call  \\\"setmax --max M DEVICE\\\"  will do a SET_MAX command\\n\"\r\n\"to set the non-volatile max number of accessible sectors to M.\\n\"\r\n\"\\n\"\r\n\"The call  \\\"setmax --delta D DEVICE\\\"  will do a SET_MAX command\\n\"\r\n\"to set the maximum accessible sector number D sectors\\n\"\r\n\"below end-of-disk.\\n\"\r\n\"\\n\"\r\n\"The call  \\\"setmax DEVICE\\\"  will do a READ_NATIVE_MAX_ADDRESS\\n\"\r\n\"command, and report the maximum accessible sector number.\\n\"\r\n\"\\n\"\r\n\"This is IDE-only. Probably DEVICE is \/dev\/hdx for some x.\\n\\n\";\r\n\r\nmain(int argc, char **argv){\r\n\tint fd, c;\r\n\tint delta, max, volat;\r\n\r\n\t\/* If you modify device, also update slave, if necessary. *\/\r\n\t\/* The kernel already does this for us since 2.4.0test9. *\/\r\n\t\/* master: hda, hdc, hde; slave: hdb, hdd, hdf *\/\r\n\tchar *device = NULL;\t\/* e.g. \"\/dev\/hda\" *\/\r\n\tint slave = 0;\r\n\r\n\tdelta = max = volat = -1;\r\n\twhile ((c = getopt_long (argc, argv, short_opts, long_opts, NULL)) != -1) {\r\n\t\tswitch(c) {\r\n\t\tcase 'd':\r\n\t\t\tdelta = atoi(optarg);\r\n\t\t\tvolat = 1;\r\n\t\t\tbreak;\r\n\t\tcase 'm':\r\n\t\t\tmax = atoi(optarg);\r\n\t\t\tvolat = 0;\r\n\t\t\tbreak;\r\n\t\tcase '?':\r\n\t\tdefault:\r\n\t\t\tfprintf(stderr, \"unknown option\\n\");\r\n\t\t\tfprintf(stderr, usage_txt);\r\n\t\t\texit(1);\r\n\t\t}\r\n\t}\r\n\r\n\tif (optind &lt; argc)\r\n\t\tdevice = argv[optind];\r\n\tif (!device) {\r\n\t\tfprintf(stderr, \"no device specified - \"\r\n\t\t\t\"use e.g. \\\"setmax \/dev\/hdb\\\"\\n\");\r\n\t\tfprintf(stderr, usage_txt);\r\n\t\texit(1);\r\n\t}\r\n\tprintf(\"Using device %s\\n\", device);\r\n\r\n\tfd = open(device, O_RDONLY);\r\n\tif (fd == -1) {\r\n\t\tperror(\"open\");\r\n\t\texit(1);\r\n\t}\r\n\r\n\tif (delta != -1 || max != -1) {\r\n\t\tif (delta != -1)\r\n\t\t\tprintf(\"setting delta=%d\\n\", delta);\r\n\t\telse\r\n\t\t\tprintf(\"setting max=%d\\n\", max);\r\n\t\tset_max_address(fd, slave, delta, max, volat);\r\n\t} else {\r\n\t\tint mad = get_native_max(fd, slave);\r\n\t\tlong long bytes = (long long) (mad+1) * 512;\r\n\t\tint hMB = (bytes+50000000)\/100000000;\r\n\r\n\t\tprintf(\"native max address: %d\\n\", mad);\r\n\t\tprintf(\"that is %lld bytes, %d.%d GB\\n\",\r\n\t\t       bytes, hMB\/10, hMB%10);\r\n\t}\r\n\tget_identity(fd);\r\n\r\n\treturn 0;\r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\/* setmax.c - aeb, 000326 - use on 2.4.0test9 or newer  [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[47,48],"class_list":["post-27","post","type-post","status-publish","format-standard","hentry","category-Technical_literature","tag-hpa","tag-setmax"],"views":1741,"_links":{"self":[{"href":"https:\/\/www.datarelab.com\/blog\/wp-json\/wp\/v2\/posts\/27","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.datarelab.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.datarelab.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.datarelab.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.datarelab.com\/blog\/wp-json\/wp\/v2\/comments?post=27"}],"version-history":[{"count":0,"href":"https:\/\/www.datarelab.com\/blog\/wp-json\/wp\/v2\/posts\/27\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.datarelab.com\/blog\/wp-json\/wp\/v2\/media?parent=27"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.datarelab.com\/blog\/wp-json\/wp\/v2\/categories?post=27"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.datarelab.com\/blog\/wp-json\/wp\/v2\/tags?post=27"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}