]> git.proxmox.com Git - mirror_smartmontools-debian.git/blob - knowndrives.cpp
6018fb8df90dddb93172c6de682f0a5a40173b84
[mirror_smartmontools-debian.git] / knowndrives.cpp
1 /*
2 * knowndrives.cpp
3 *
4 * Home page of code is: http://smartmontools.sourceforge.net
5 * Address of support mailing list: smartmontools-support@lists.sourceforge.net
6 *
7 * Copyright (C) 2003-7 Philip Williams, Bruce Allen
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * You should have received a copy of the GNU General Public License
15 * (for example COPYING); if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 *
18 */
19
20 #include "config.h"
21 #include "int64.h"
22 #include <stdio.h>
23 #include "atacmds.h"
24 #include "ataprint.h"
25 #include "extern.h"
26 #include "knowndrives.h"
27 #include "utility.h" // includes <regex.h>
28
29 const char *knowndrives_c_cvsid="$Id: knowndrives.cpp,v 1.162 2007/11/05 00:29:11 geoffk1 Exp $"
30 ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID KNOWNDRIVES_H_CVSID UTILITY_H_CVSID;
31
32 #define MODEL_STRING_LENGTH 40
33 #define FIRMWARE_STRING_LENGTH 8
34 #define TABLEPRINTWIDTH 19
35
36 // See vendorattributeargs[] array in atacmds.cpp for definitions.
37 #define PRESET_9_MINUTES { 9, 1 }
38 #define PRESET_9_TEMP { 9, 2 }
39 #define PRESET_9_SECONDS { 9, 3 }
40 #define PRESET_9_HALFMINUTES { 9, 4 }
41 #define PRESET_192_EMERGENCYRETRACTCYCLECT { 192, 1 }
42 #define PRESET_193_LOADUNLOAD { 193, 1 }
43 #define PRESET_194_10XCELSIUS { 194, 1 }
44 #define PRESET_194_UNKNOWN { 194, 2 }
45 #define PRESET_198_OFFLINESCANUNCSECTORCT { 198, 1 }
46 #define PRESET_200_WRITEERRORCOUNT { 200, 1 }
47 #define PRESET_201_DETECTEDTACOUNT { 201, 1 }
48 #define PRESET_220_TEMP { 220, 1 }
49
50 /* Arrays of preset vendor-specific attribute options for use in
51 * knowndrives[]. */
52
53 extern int64_t bytes;
54
55 // to hold onto exit code for atexit routine
56 extern int exitstatus;
57
58 // These three are common to several models.
59 const unsigned char vendoropts_9_minutes[][2] = {
60 PRESET_9_MINUTES,
61 {0,0}
62 };
63 const unsigned char vendoropts_9_halfminutes[][2] = {
64 PRESET_9_HALFMINUTES,
65 {0,0}
66 };
67 const unsigned char vendoropts_9_seconds[][2] = {
68 PRESET_9_SECONDS,
69 {0,0}
70 };
71
72 const unsigned char vendoropts_Maxtor_4D080H4[][2] = {
73 PRESET_9_MINUTES,
74 PRESET_194_UNKNOWN,
75 {0,0}
76 };
77
78 const unsigned char vendoropts_Fujitsu_MHS2020AT[][2] = {
79 PRESET_9_SECONDS,
80 PRESET_192_EMERGENCYRETRACTCYCLECT,
81 PRESET_198_OFFLINESCANUNCSECTORCT,
82 PRESET_200_WRITEERRORCOUNT,
83 PRESET_201_DETECTEDTACOUNT,
84 {0,0}
85 };
86
87 const unsigned char vendoropts_Fujitsu_MHR2040AT[][2] = {
88 PRESET_9_SECONDS,
89 PRESET_192_EMERGENCYRETRACTCYCLECT,
90 PRESET_198_OFFLINESCANUNCSECTORCT,
91 PRESET_200_WRITEERRORCOUNT,
92 {0,0}
93 };
94
95 const unsigned char vendoropts_Samsung_SV4012H[][2] = {
96 PRESET_9_HALFMINUTES,
97 {0,0}
98 };
99
100 const unsigned char vendoropts_Samsung_SV1204H[][2] = {
101 PRESET_9_HALFMINUTES,
102 PRESET_194_10XCELSIUS,
103 {0,0}
104 };
105
106 const unsigned char vendoropts_Hitachi_DK23XX[][2] = {
107 PRESET_9_MINUTES,
108 PRESET_193_LOADUNLOAD,
109 {0,0}
110 };
111
112 const char same_as_minus_F[]="Fixes byte order in some SMART data (same as -F samsung)";
113 const char same_as_minus_F2[]="Fixes byte order in some SMART data (same as -F samsung2)";
114 const char same_as_minus_F3[]="Fixes completed self-test reported as in progress (same as -F samsung3)";
115
116 const char may_need_minus_F_disabled[] ="May need -F samsung disabled; see manual for details.";
117 const char may_need_minus_F2_disabled[]="May need -F samsung2 disabled; see manual for details.";
118 const char may_need_minus_F2_enabled[] ="May need -F samsung2 enabled; see manual for details.";
119 const char may_need_minus_F_enabled[] ="May need -F samsung or -F samsung2 enabled; see manual for details.";
120 const char may_need_minus_F3_enabled[] ="May need -F samsung3 enabled; see manual for details.";
121
122 /* Special-purpose functions for use in knowndrives[]. */
123 void specialpurpose_reverse_samsung(smartmonctrl *con)
124 {
125 if (con->fixfirmwarebug==FIX_NOTSPECIFIED)
126 con->fixfirmwarebug = FIX_SAMSUNG;
127 }
128 void specialpurpose_reverse_samsung2(smartmonctrl *con)
129 {
130 if (con->fixfirmwarebug==FIX_NOTSPECIFIED)
131 con->fixfirmwarebug = FIX_SAMSUNG2;
132 }
133 void specialpurpose_fix_samsung3(smartmonctrl *con)
134 {
135 if (con->fixfirmwarebug==FIX_NOTSPECIFIED)
136 con->fixfirmwarebug = FIX_SAMSUNG3;
137 }
138
139 /* Table of settings for known drives terminated by an element containing all
140 * zeros. The drivesettings structure is described in knowndrives.h. Note
141 * that lookupdrive() will search knowndrives[] from the start to end or
142 * until it finds the first match, so the order in knowndrives[] is important
143 * for distinct entries that could match the same drive. */
144
145 // Note that the table just below uses EXTENDED REGULAR EXPRESSIONS.
146 // A good on-line reference for these is:
147 // http://www.zeus.com/extra/docsystem/docroot/apps/web/docs/modules/access/regex.html
148
149 const drivesettings knowndrives[] = {
150 { "IBM Deskstar 60GXP series", // ER60A46A firmware
151 "(IBM-|Hitachi )?IC35L0[12346]0AVER07",
152 "^ER60A46A$",
153 NULL, NULL, NULL, NULL
154 },
155 { "IBM Deskstar 60GXP series", // All other firmware
156 "(IBM-|Hitachi )?IC35L0[12346]0AVER07",
157 ".*",
158 "IBM Deskstar 60GXP drives may need upgraded SMART firmware.\n"
159 "Please see http://www.geocities.com/dtla_update/index.html#rel and\n"
160 "http://www-3.ibm.com/pc/support/site.wss/document.do?lndocid=MIGR-42215 or\n"
161 "http://www-1.ibm.com/support/docview.wss?uid=psg1MIGR-42215",
162 NULL, NULL, NULL
163 },
164 { "IBM Deskstar 40GV & 75GXP series (A5AA/A6AA firmware)",
165 "(IBM-)?DTLA-30[57]0[123467][05]",
166 "^T[WX][123468AG][OF]A[56]AA$",
167 NULL, NULL, NULL, NULL
168 },
169 { "IBM Deskstar 40GV & 75GXP series (all other firmware)",
170 "(IBM-)?DTLA-30[57]0[123467][05]",
171 ".*",
172 "IBM Deskstar 40GV and 75GXP drives may need upgraded SMART firmware.\n"
173 "Please see http://www.geocities.com/dtla_update/ and\n"
174 "http://www-3.ibm.com/pc/support/site.wss/document.do?lndocid=MIGR-42215 or\n"
175 "http://www-1.ibm.com/support/docview.wss?uid=psg1MIGR-42215",
176 NULL, NULL, NULL
177 },
178 { NULL, // ExcelStor J240, J340, J360, J680, and J880
179 "^ExcelStor Technology J(24|34|36|68|88)0$",
180 ".*",
181 NULL, NULL, NULL, NULL
182 },
183 { NULL, // Fujitsu M1623TAU
184 "^FUJITSU M1623TAU$",
185 ".*",
186 NULL,
187 vendoropts_9_seconds,
188 NULL, NULL
189 },
190 { "Fujitsu MHG series",
191 "^FUJITSU MHG2...ATU?",
192 ".*",
193 NULL,
194 vendoropts_9_seconds,
195 NULL, NULL
196 },
197 { "Fujitsu MHH series",
198 "^FUJITSU MHH2...ATU?",
199 ".*",
200 NULL,
201 vendoropts_9_seconds,
202 NULL, NULL
203 },
204 { "Fujitsu MHJ series",
205 "^FUJITSU MHJ2...ATU?",
206 ".*",
207 NULL,
208 vendoropts_9_seconds,
209 NULL, NULL
210 },
211 { "Fujitsu MHK series",
212 "^FUJITSU MHK2...ATU?",
213 ".*",
214 NULL,
215 vendoropts_9_seconds,
216 NULL, NULL
217 },
218 { NULL, // Fujitsu MHL2300AT
219 "^FUJITSU MHL2300AT$",
220 ".*",
221 "This drive's firmware has a harmless Drive Identity Structure\n"
222 "checksum error bug.",
223 vendoropts_9_seconds,
224 NULL, NULL
225 },
226 { NULL, // MHM2200AT, MHM2150AT, MHM2100AT, MHM2060AT
227 "^FUJITSU MHM2(20|15|10|06)0AT$",
228 ".*",
229 "This drive's firmware has a harmless Drive Identity Structure\n"
230 "checksum error bug.",
231 vendoropts_9_seconds,
232 NULL, NULL
233 },
234 { "Fujitsu MHN series",
235 "^FUJITSU MHN2...AT$",
236 ".*",
237 NULL,
238 vendoropts_9_seconds,
239 NULL, NULL
240 },
241 { NULL, // Fujitsu MHR2020AT
242 "^FUJITSU MHR2020AT$",
243 ".*",
244 NULL,
245 vendoropts_9_seconds,
246 NULL, NULL
247 },
248 { NULL, // Fujitsu MHR2040AT
249 "^FUJITSU MHR2040AT$",
250 ".*", // Tested on 40BA
251 NULL,
252 vendoropts_Fujitsu_MHR2040AT,
253 NULL, NULL
254 },
255 { "Fujitsu MHSxxxxAT family",
256 "^FUJITSU MHS20[6432]0AT( .)?$",
257 ".*",
258 NULL,
259 vendoropts_Fujitsu_MHS2020AT,
260 NULL, NULL
261 },
262 { "Fujitsu MHT series",
263 "^FUJITSU MHT2...(AH|AS|AT|BH)U?",
264 ".*",
265 NULL,
266 vendoropts_9_seconds,
267 NULL, NULL
268 },
269 { "Fujitsu MHU series",
270 "^FUJITSU MHU2...ATU?",
271 ".*",
272 NULL,
273 vendoropts_9_seconds,
274 NULL, NULL
275 },
276 { "Fujitsu MHV series",
277 "^FUJITSU MHV2...(AH|AS|AT|BH|BS|BT)",
278 ".*",
279 NULL,
280 vendoropts_9_seconds,
281 NULL, NULL
282 },
283 { "Fujitsu MPA..MPG series",
284 "^FUJITSU MP[A-G]3...A[HTEV]U?",
285 ".*",
286 NULL,
287 vendoropts_9_seconds,
288 NULL, NULL
289 },
290 { NULL, // Samsung SV4012H (known firmware)
291 "^SAMSUNG SV4012H$",
292 "^RM100-08$",
293 NULL,
294 vendoropts_Samsung_SV4012H,
295 specialpurpose_reverse_samsung,
296 same_as_minus_F
297 },
298 { NULL, // Samsung SV4012H (all other firmware)
299 "^SAMSUNG SV4012H$",
300 ".*",
301 may_need_minus_F_disabled,
302 vendoropts_Samsung_SV4012H,
303 specialpurpose_reverse_samsung,
304 same_as_minus_F
305 },
306 { NULL, // Samsung SV0412H (known firmware)
307 "^SAMSUNG SV0412H$",
308 "^SK100-01$",
309 NULL,
310 vendoropts_Samsung_SV1204H,
311 specialpurpose_reverse_samsung,
312 same_as_minus_F
313 },
314 { NULL, // Samsung SV0412H (all other firmware)
315 "^SAMSUNG SV0412H$",
316 ".*",
317 may_need_minus_F_disabled,
318 vendoropts_Samsung_SV1204H,
319 specialpurpose_reverse_samsung,
320 same_as_minus_F
321 },
322 { NULL, // Samsung SV1204H (known firmware)
323 "^SAMSUNG SV1204H$",
324 "^RK100-1[3-5]$",
325 NULL,
326 vendoropts_Samsung_SV1204H,
327 specialpurpose_reverse_samsung,
328 same_as_minus_F
329 },
330 { NULL, // Samsung SV1204H (all other firmware)
331 "^SAMSUNG SV1204H$",
332 ".*",
333 may_need_minus_F_disabled,
334 vendoropts_Samsung_SV1204H,
335 specialpurpose_reverse_samsung,
336 same_as_minus_F
337 },
338 { NULL, // SAMSUNG SV0322A tested with FW JK200-35
339 "^SAMSUNG SV0322A$",
340 ".*",
341 NULL,
342 NULL,
343 NULL,
344 NULL
345 },
346 { NULL, // SAMSUNG SP40A2H with RR100-07 firmware
347 "^SAMSUNG SP40A2H$",
348 "^RR100-07$",
349 NULL,
350 vendoropts_9_halfminutes,
351 specialpurpose_reverse_samsung,
352 same_as_minus_F
353 },
354 { NULL, // SAMSUNG SP8004H with QW100-61 firmware
355 "^SAMSUNG SP8004H$",
356 "^QW100-61$",
357 NULL,
358 vendoropts_9_halfminutes,
359 specialpurpose_reverse_samsung,
360 same_as_minus_F
361 },
362 { "SAMSUNG SpinPoint T133 series", // tested with HD300LJ/ZT100-12, HD400LJ/ZZ100-14, HD401LJ/ZZ100-15
363 "^SAMSUNG HD(250KD|(30[01]|320|40[01])L[DJ])$",
364 ".*",
365 NULL, NULL, NULL, NULL
366 },
367 { "SAMSUNG SpinPoint T166 series", // tested with HD501LJ/CR100-10
368 "^SAMSUNG HD(080G|160H|32[01]K|403L|50[01]L)J$",
369 ".*",
370 NULL, NULL, NULL, NULL
371 },
372 { "SAMSUNG SpinPoint P120 series", // VF100-37 firmware, tested with SP2514N/VF100-37
373 "^SAMSUNG SP(16[01]3|2[05][01]4)[CN]$",
374 "^VF100-37$",
375 NULL, NULL,
376 specialpurpose_fix_samsung3,
377 same_as_minus_F3
378 },
379 { "SAMSUNG SpinPoint P120 series", // other firmware, tested with SP2504C/VT100-33
380 "^SAMSUNG SP(16[01]3|2[05][01]4)[CN]$",
381 ".*",
382 may_need_minus_F3_enabled,
383 NULL, NULL, NULL
384 },
385 { "SAMSUNG SpinPoint P80 SD series", // tested with HD160JJ/ZM100-33
386 "^SAMSUNG HD(080H|120I|160J)J$",
387 ".*",
388 NULL, NULL, NULL, NULL
389 },
390 { "SAMSUNG SpinPoint P80 series", // BH100-35 firmware, tested with SP0842N/BH100-35
391 "^SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]$",
392 "^BH100-35$",
393 NULL, NULL,
394 specialpurpose_fix_samsung3,
395 same_as_minus_F3
396 },
397 { "SAMSUNG SpinPoint P80 series", // firmware *-35 or later
398 "^SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]$",
399 ".*-3[5-9]$",
400 may_need_minus_F3_enabled,
401 NULL, NULL, NULL
402 },
403 { "SAMSUNG SpinPoint P80 series", // firmware *-26...34, tested with SP1614C/SW100-34
404 "^SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]$",
405 ".*-(2[6789]|3[0-4])$",
406 NULL,
407 vendoropts_9_halfminutes,
408 NULL, NULL
409 },
410 {
411 NULL, // Any other Samsung disk with *-23 *-24 firmware
412 // SAMSUNG SP1213N (TL100-23 firmware)
413 // SAMSUNG SP0802N (TK100-23 firmware)
414 // Samsung SP1604N, tested with FW TM100-23 and TM100-24
415 "^SAMSUNG .*$",
416 ".*-2[34]$",
417 NULL,
418 vendoropts_Samsung_SV4012H,
419 specialpurpose_reverse_samsung2,
420 same_as_minus_F2
421 },
422 { NULL, // All Samsung drives with '.*-25' firmware
423 "^SAMSUNG.*",
424 ".*-25$",
425 may_need_minus_F2_disabled,
426 vendoropts_Samsung_SV4012H,
427 specialpurpose_reverse_samsung2,
428 same_as_minus_F2
429 },
430 { NULL, // All Samsung drives with '.*-26 or later (currently to -39)' firmware
431 "^SAMSUNG.*",
432 ".*-(2[6789]|3[0-9])$",
433 NULL,
434 vendoropts_Samsung_SV4012H,
435 NULL,
436 NULL
437 },
438 { NULL, // Samsung ALL OTHER DRIVES
439 "^SAMSUNG.*",
440 ".*",
441 may_need_minus_F_enabled,
442 NULL, NULL, NULL
443 },
444 { "Maxtor Fireball 541DX family",
445 "^Maxtor 2B0(0[468]|1[05]|20)H1$",
446 ".*",
447 NULL,
448 vendoropts_Maxtor_4D080H4,
449 NULL, NULL
450 },
451 { "Maxtor Fireball 3 family",
452 "^Maxtor 2F0[234]0[JL]0$",
453 ".*",
454 NULL,
455 vendoropts_9_minutes,
456 NULL, NULL
457 },
458 { "Maxtor DiamondMax 2160 Ultra ATA family",
459 "^Maxtor 8(2160D2|3228D3|3240D3|4320D4|6480D6|8400D8|8455D8)$",
460 ".*",
461 NULL,
462 vendoropts_9_minutes,
463 NULL, NULL
464 },
465 { "Maxtor DiamondMax 2880 Ultra ATA family",
466 "^Maxtor 9(0510D4|0576D4|0648D5|0720D5|0840D6|0845D6|0864D6|1008D7|1080D8|1152D8)$",
467 ".*",
468 NULL,
469 vendoropts_9_minutes,
470 NULL, NULL
471 },
472 { "Maxtor DiamondMax 3400 Ultra ATA family",
473 "^Maxtor 9(1(360|350|202)D8|1190D7|10[12]0D6|0840D5|06[48]0D4|0510D3|1(350|202)E8|1010E6|0840E5|0640E4)$",
474 ".*",
475 NULL,
476 vendoropts_9_minutes,
477 NULL, NULL
478 },
479 { "Maxtor DiamondMax D540X-4G family",
480 "^Maxtor 4G(120J6|160J[68])$",
481 ".*",
482 NULL,
483 vendoropts_Maxtor_4D080H4,
484 NULL, NULL
485 },
486 { "Maxtor DiamondMax D540X-4K family",
487 "^MAXTOR 4K(020H1|040H2|060H3|080H4)$",
488 ".*",
489 NULL, NULL, NULL, NULL
490 },
491 { "Maxtor DiamondMax Plus D740X family",
492 "^MAXTOR 6L0(20[JL]1|40[JL]2|60[JL]3|80[JL]4)$",
493 ".*",
494 NULL, NULL, NULL, NULL
495 },
496 { "Maxtor DiamondMax Plus 5120 Ultra ATA 33 family",
497 "^Maxtor 9(0512D2|0680D3|0750D3|0913D4|1024D4|1360D6|1536D6|1792D7|2048D8)$",
498 ".*",
499 NULL,
500 vendoropts_9_minutes,
501 NULL, NULL
502 },
503 { "Maxtor DiamondMax Plus 6800 Ultra ATA 66 family",
504 "^Maxtor 9(2732U8|2390U7|2049U6|1707U5|1366U4|1024U3|0845U3|0683U2)$",
505 ".*",
506 NULL,
507 vendoropts_9_minutes,
508 NULL, NULL
509 },
510 { "Maxtor DiamondMax D540X-4D",
511 "^Maxtor 4D0(20H1|40H2|60H3|80H4)$",
512 ".*",
513 NULL,
514 vendoropts_Maxtor_4D080H4,
515 NULL, NULL
516 },
517 { "Maxtor DiamondMax 16 family",
518 "^Maxtor 4(R0[68]0[JL]0|R1[26]0L0|A160J0|R120L4)$",
519 ".*",
520 NULL,
521 vendoropts_9_minutes,
522 NULL, NULL
523 },
524 { "Maxtor DiamondMax 4320 Ultra ATA family",
525 "^Maxtor (91728D8|91512D7|91303D6|91080D5|90845D4|90645D3|90648D[34]|90432D2)$",
526 ".*",
527 NULL,
528 vendoropts_9_minutes,
529 NULL, NULL
530 },
531 { "Maxtor DiamondMax 17 VL family",
532 "^Maxtor 9(0431U1|0641U2|0871U2|1301U3|1741U4)$",
533 ".*",
534 NULL,
535 vendoropts_9_minutes,
536 NULL, NULL
537 },
538 { "Maxtor DiamondMax 20 VL family",
539 "^Maxtor (94091U8|93071U6|92561U5|92041U4|91731U4|91531U3|91361U3|91021U2|90841U2|90651U2)$",
540 ".*",
541 NULL,
542 vendoropts_9_minutes,
543 NULL, NULL
544 },
545 { "Maxtor DiamondMax VL 30 family",
546 "^Maxtor (33073U4|32049U3|31536U2|30768U1)$",
547 ".*",
548 NULL,
549 vendoropts_9_minutes,
550 NULL, NULL
551 },
552 { "Maxtor DiamondMax 36 family",
553 "^Maxtor (93652U8|92739U6|91826U4|91369U3|90913U2|90845U2|90435U1)$",
554 ".*",
555 NULL,
556 vendoropts_9_minutes,
557 NULL, NULL
558 },
559 { "Maxtor DiamondMax 40 ATA 66 series",
560 "^Maxtor 9(0684U2|1024U2|1362U3|1536U3|2049U4|2562U5|3073U6|4098U8)$",
561 ".*",
562 NULL,
563 vendoropts_9_minutes,
564 NULL, NULL
565 },
566 { "Maxtor DiamondMax Plus 40 series (Ultra ATA 66 and Ultra ATA 100)",
567 "^Maxtor (54098[UH]8|53073[UH]6|52732[UH]6|52049[UH]4|51536[UH]3|51369[UH]3|51024[UH]2)$",
568 ".*",
569 NULL,
570 vendoropts_9_minutes,
571 NULL, NULL
572 },
573 { "Maxtor DiamondMax 40 VL Ultra ATA 100 series",
574 "^Maxtor 3(1024H1|1535H2|2049H2|3073H3|4098H4)( B)?$",
575 ".*",
576 NULL,
577 vendoropts_9_minutes,
578 NULL, NULL
579 },
580 { "Maxtor DiamondMax Plus 45 Ulta ATA 100 family",
581 "^Maxtor 5(4610H6|4098H6|3073H4|2049H3|1536H2|1369H2|1023H2)$",
582 ".*",
583 NULL,
584 vendoropts_9_minutes,
585 NULL, NULL
586 },
587 { "Maxtor DiamondMax 60 ATA 66 family",
588 "^Maxtor 9(1023U2|1536U2|2049U3|2305U3|3073U4|4610U6|6147U8)$",
589 ".*",
590 NULL,
591 vendoropts_9_minutes,
592 NULL, NULL
593 },
594 { "Maxtor DiamondMax 60 ATA 100 family",
595 "^Maxtor 9(1023H2|1536H2|2049H3|2305H3|3073H4|4610H6|6147H8)$",
596 ".*",
597 NULL,
598 vendoropts_9_minutes,
599 NULL, NULL
600 },
601 { "Maxtor DiamondMax Plus 60 family",
602 "^Maxtor 5T0(60H6|40H4|30H3|20H2|10H1)$",
603 ".*",
604 NULL,
605 vendoropts_9_minutes,
606 NULL, NULL
607 },
608 { "Maxtor DiamondMax 80 family",
609 "^Maxtor (98196H8|96147H6)$",
610 ".*",
611 NULL,
612 vendoropts_9_minutes,
613 NULL, NULL
614 },
615 { "Maxtor DiamondMax 536DX family",
616 "^Maxtor 4W(100H6|080H6|060H4|040H3|030H2)$",
617 ".*",
618 NULL,
619 vendoropts_9_minutes,
620 NULL, NULL
621 },
622 { "Maxtor DiamondMax Plus 8 family",
623 "^Maxtor 6(E0[234]|K04)0L0$",
624 ".*",
625 NULL,
626 vendoropts_9_minutes,
627 NULL, NULL
628 },
629 { "Maxtor DiamondMax 10 family (ATA/133 and SATA/150)",
630 "^Maxtor 6(B(30|25|20|16|12|08)0[MPRS]|L(080[MLP]|(100|120)[MP]|160[MP]|200[MPRS]|250[RS]|300[RS]))0$",
631 ".*",
632 NULL,
633 vendoropts_9_minutes,
634 NULL, NULL
635 },
636 { "Maxtor DiamondMax 10 family (SATA/300)",
637 "^Maxtor 6V(080E|160E|200E|250F|300F|320F)0$",
638 ".*",
639 NULL, NULL, NULL, NULL
640 },
641 { "Maxtor DiamondMax Plus 9 family",
642 "^Maxtor 6Y((060|080|120|160)L0|(060|080|120|160|200|250)P0|(060|080|120|160|200|250)M0)$",
643 ".*",
644 NULL,
645 vendoropts_9_minutes,
646 NULL, NULL
647 },
648 { "Maxtor DiamondMax 11 family",
649 "^Maxtor 6H[45]00[FR]0$",
650 ".*",
651 NULL, NULL, NULL, NULL
652 },
653 { "Maxtor MaXLine Plus II",
654 "^Maxtor 7Y250[PM]0$",
655 ".*",
656 NULL,
657 vendoropts_9_minutes,
658 NULL, NULL
659 },
660 { "Maxtor MaXLine II family",
661 "^Maxtor [45]A(25|30|32)0[JN]0$",
662 ".*",
663 NULL,
664 vendoropts_9_minutes,
665 NULL, NULL
666 },
667 { "Maxtor MaXLine III family (ATA/133 and SATA/150)",
668 "^Maxtor 7L(25|30)0[SR]0$",
669 ".*",
670 NULL,
671 vendoropts_9_minutes,
672 NULL, NULL
673 },
674 { "Maxtor MaXLine III family (SATA/300)",
675 "^Maxtor 7V(25|30)0F0$",
676 ".*",
677 NULL, NULL, NULL, NULL
678 },
679 { "Maxtor MaXLine Pro 500 family", // There is also a 7H500R0 model, but I
680 "^Maxtor 7H500F0$", // haven't added it because I suspect
681 ".*", // it might need vendoropts_9_minutes
682 NULL, NULL, NULL, NULL // and nobody has submitted a report yet
683 },
684 { NULL, // HITACHI_DK14FA-20B
685 "^HITACHI_DK14FA-20B$",
686 ".*",
687 NULL,
688 vendoropts_Hitachi_DK23XX,
689 NULL, NULL
690 },
691 { "HITACHI Travelstar DK23XX/DK23XXB series",
692 "^HITACHI_DK23..-..B?$",
693 ".*",
694 NULL,
695 vendoropts_Hitachi_DK23XX,
696 NULL, NULL
697 },
698 { "Hitachi Endurastar J4K20/N4K20 (formerly DK23FA-20J)",
699 "^(HITACHI_DK23FA-20J|HTA422020F9AT[JN]0)$",
700 ".*",
701 NULL,
702 vendoropts_Hitachi_DK23XX,
703 NULL, NULL
704 },
705 { "IBM Deskstar 14GXP and 16GP series",
706 "^IBM-DTTA-3(7101|7129|7144|5032|5043|5064|5084|5101|5129|5168)0$",
707 ".*",
708 NULL, NULL, NULL, NULL
709 },
710 { "IBM Deskstar 25GP and 22GXP family",
711 "^IBM-DJNA-3(5(101|152|203|250)|7(091|135|180|220))0$",
712 ".*",
713 NULL, NULL, NULL, NULL
714 },
715 { "IBM Travelstar 4GT family",
716 "^IBM-DTCA-2(324|409)0$",
717 ".*",
718 NULL, NULL, NULL, NULL
719 },
720 { "IBM Travelstar 25GS, 18GT, and 12GN family",
721 "^IBM-DARA-2(25|18|15|12|09|06)000$",
722 ".*",
723 NULL, NULL, NULL, NULL
724 },
725 { "IBM Travelstar 48GH, 30GN, and 15GN family",
726 "^(IBM-|Hitachi )?IC25(T048ATDA05|N0(30|20|15|12|10|07|06|05)ATDA04)-.$",
727 ".*",
728 NULL, NULL, NULL, NULL
729 },
730 { "IBM Travelstar 32GH, 30GT, and 20GN family",
731 "^IBM-DJSA-2(32|30|20|10|05)$",
732 ".*",
733 NULL, NULL, NULL, NULL
734 },
735 { "IBM Travelstar 4GN family",
736 "^IBM-DKLA-2(216|324|432)0$",
737 ".*",
738 NULL, NULL, NULL, NULL
739 },
740 { "IBM Deskstar 37GP and 34GXP family",
741 "^IBM-DPTA-3(5(375|300|225|150)|7(342|273|205|136))0$",
742 ".*",
743 NULL, NULL, NULL, NULL
744 },
745 { "IBM/Hitachi Travelstar 60GH and 40GN family",
746 "^(IBM-|Hitachi )?IC25(T060ATC[SX]05|N0[4321]0ATC[SX]04)-.$",
747 ".*",
748 NULL, NULL, NULL, NULL
749 },
750 { "IBM/Hitachi Travelstar 40GNX family",
751 "^(IBM-|Hitachi )?IC25N0[42]0ATC[SX]05-.$",
752 ".*",
753 NULL, NULL, NULL, NULL
754 },
755 { "Hitachi Travelstar 80GN family",
756 "^(Hitachi )?IC25N0[23468]0ATMR04-.$",
757 ".*",
758 NULL, NULL, NULL, NULL
759 },
760 { "Hitachi Travelstar 5K80 family",
761 "^HTS5480[8642]0M9AT00$",
762 ".*",
763 NULL, NULL, NULL, NULL
764 },
765 { "Hitachi Travelstar 5K100 series",
766 "^HTS5410[1864]0G9(AT|SA)00$",
767 ".*",
768 NULL, NULL, NULL, NULL
769 },
770 { "Hitachi Travelstar E5K100 series",
771 "^HTE541040G9(AT|SA)00$",
772 ".*",
773 NULL, NULL, NULL, NULL
774 },
775 { "Hitachi Travelstar 5K160 series",
776 "^(Hitachi )?HTS5416([468]0|1[26])J9(AT|SA)00$",
777 ".*",
778 NULL, NULL, NULL, NULL
779 },
780 { "Hitachi Travelstar 7K60",
781 "^HTS726060M9AT00$",
782 ".*",
783 NULL, NULL, NULL, NULL
784 },
785 { "Hitachi Travelstar 7K100",
786 "^HTS7210[168]0G9(AT|SA)00$",
787 ".*",
788 NULL, NULL, NULL, NULL
789 },
790 { "Hitachi Travelstar E7K100",
791 "^HTE7210[168]0G9(AT|SA)00$",
792 ".*",
793 NULL, NULL, NULL, NULL
794 },
795 { "Hitachi Travelstar E7K60 family",
796 "^HTE7260[46]0M9AT00$",
797 ".*",
798 NULL, NULL, NULL, NULL
799 },
800 { "IBM/Hitachi Deskstar 120GXP family",
801 "^(IBM-)?IC35L((020|040|060|080|120)AVVA|0[24]0AVVN)07-[01]$",
802 ".*",
803 NULL, NULL, NULL, NULL
804 },
805 { "IBM/Hitachi Deskstar GXP-180 family",
806 "^(IBM-)?IC35L(030|060|090|120|180)AVV207-[01]$",
807 ".*",
808 NULL, NULL, NULL, NULL
809 },
810 { "IBM Travelstar 14GS",
811 "^IBM-DCYA-214000$",
812 ".*",
813 NULL, NULL, NULL, NULL
814 },
815 { "IBM Travelstar 4LP",
816 "^IBM-DTNA-2(180|216)0$",
817 ".*",
818 NULL, NULL, NULL, NULL
819 },
820 { "Hitachi Deskstar 7K80 series",
821 "^(Hitachi )?HDS7280([48]0PLAT20|(40)?PLA320|80PLA380)$",
822 ".*",
823 NULL, NULL, NULL, NULL
824 },
825 { "Hitachi Deskstar 7K250 series",
826 "^(Hitachi )?HDS7225((40|80|12|16)VLAT20|(12|16|25)VLAT80|(80|12|16|25)VLSA80)$",
827 ".*",
828 NULL, NULL, NULL, NULL
829 },
830 { "Hitachi Deskstar T7K250 series",
831 "^(Hitachi )?HDT7225((25|20|16)DLA(T80|380))$",
832 ".*",
833 NULL, NULL, NULL, NULL
834 },
835 { "Hitachi Deskstar 7K400 series",
836 "^(Hitachi )?HDS724040KL(AT|SA)80$",
837 ".*",
838 NULL, NULL, NULL, NULL
839 },
840 { "Hitachi Deskstar 7K500 series",
841 "^(Hitachi )?HDS725050KLA(360|T80)$",
842 ".*",
843 NULL, NULL, NULL, NULL
844 },
845 { "Toshiba 2.5\" HDD series (30-60 GB)",
846 "^TOSHIBA MK((6034|4032)GSX|(6034|4032)GAX|(6026|4026|4019|3019)GAXB?|(6025|6021|4025|4021|4018|3021|3018)GAS|(4036|3029)GACE?|(4018|3017)GAP)$",
847 ".*",
848 NULL, NULL, NULL, NULL
849 },
850 { "Toshiba 2.5\" HDD series (80 GB and above)",
851 "^TOSHIBA MK(80(25GAS|26GAX|32GAX|32GSX)|10(31GAS|32GAX)|12(33GAS|34G[AS]X)|2035GSS)$",
852 ".*",
853 NULL, NULL, NULL, NULL
854 },
855 { NULL, // TOSHIBA MK6022GAX
856 "^TOSHIBA MK6022GAX$",
857 ".*",
858 NULL, NULL, NULL, NULL
859 },
860 { NULL, // TOSHIBA MK6409MAV
861 "^TOSHIBA MK6409MAV$",
862 ".*",
863 NULL, NULL, NULL, NULL
864 },
865 { NULL, // TOS MK3019GAXB SUN30G
866 "^TOS MK3019GAXB SUN30G$",
867 ".*",
868 NULL, NULL, NULL, NULL
869 },
870 { NULL, // TOSHIBA MK2016GAP, MK2017GAP, MK2018GAP, MK2018GAS, MK2023GAS
871 "^TOSHIBA MK20(1[678]GAP|(18|23)GAS)$",
872 ".*",
873 NULL, NULL, NULL, NULL
874 },
875 { "Seagate Momentus family",
876 "^ST9(20|28|40|48)11A$",
877 ".*",
878 NULL, NULL, NULL, NULL
879 },
880 { "Seagate Momentus 42 family",
881 "^ST9(2014|3015|4019)A$",
882 ".*",
883 NULL, NULL, NULL, NULL
884 },
885 { "Seagate Momentus 4200.2 Series",
886 "^ST9(100822|808210|60821|50212|402113|30219)A$",
887 ".*",
888 NULL, NULL, NULL, NULL
889 },
890 { "Seagate Momentus 5400.2 series",
891 "^ST9(808211|60822|408114|308110|120821|10082[34]|8823|6812|4813|3811)AS?$",
892 ".*",
893 NULL, NULL, NULL, NULL
894 },
895 { "Seagate Momentus 7200.1 series",
896 "^ST9(10021|80825|6023|4015)AS?$",
897 ".*",
898 NULL, NULL, NULL, NULL
899 },
900 { "Seagate Medalist 2110, 3221, 4321, 6531, and 8641",
901 "^ST3(2110|3221|4321|6531|8641)A$",
902 ".*",
903 NULL, NULL, NULL, NULL
904 },
905 { "Seagate U Series X family",
906 "^ST3(10014A(CE)?|20014A)$",
907 ".*",
908 NULL, NULL, NULL, NULL
909 },
910 { "Seagate U7 family",
911 "^ST3(30012|40012|60012|80022|120020)A$",
912 ".*",
913 NULL, NULL, NULL, NULL
914 },
915 { "Seagate U Series 6 family",
916 "^ST3(8002|6002|4081|3061|2041)0A$",
917 ".*",
918 NULL, NULL, NULL, NULL
919 },
920 { "Seagate U Series 5 family",
921 "^ST3(40823|30621|20413|15311|10211)A$",
922 ".*",
923 NULL, NULL, NULL, NULL
924 },
925 { "Seagate U4 family",
926 "^ST3(2112|4311|6421|8421)A$",
927 ".*",
928 NULL, NULL, NULL, NULL
929 },
930 { "Seagate U8 family",
931 "^ST3(8410|4313|17221|13021)A$",
932 ".*",
933 NULL, NULL, NULL, NULL
934 },
935 { "Seagate U10 family",
936 "^ST3(20423|15323|10212)A$",
937 ".*",
938 NULL, NULL, NULL, NULL
939 },
940 { "Seagate Barracuda ATA II family",
941 "^ST3(3063|2042|1532|1021)0A$",
942 ".*",
943 NULL, NULL, NULL, NULL
944 },
945 { "Seagate Barracuda ATA III family",
946 "^ST3(40824|30620|20414|15310|10215)A$",
947 ".*",
948 NULL, NULL, NULL, NULL
949 },
950 { "Seagate Barracuda ATA IV family",
951 "^ST3(20011|30011|40016|60021|80021)A$",
952 ".*",
953 NULL, NULL, NULL, NULL
954 },
955 { "Seagate Barracuda ATA V family",
956 "^ST3(12002(3A|4A|9A|3AS)|800(23A|15A|23AS)|60(015A|210A)|40017A)$",
957 ".*",
958 NULL, NULL, NULL, NULL
959 },
960 { "Seagate Barracuda 5400.1",
961 "^ST340015A$",
962 ".*",
963 NULL, NULL, NULL, NULL
964 },
965 { "Seagate Barracuda 7200.7 and 7200.7 Plus family",
966 "^ST3(200021A|200822AS?|16002[13]AS?|12002[26]AS?|1[26]082[78]AS|8001[13]AS?|80817AS|60014A|40111AS|40014AS?)$",
967 ".*",
968 NULL, NULL, NULL, NULL
969 },
970 { "Seagate Barracuda 7200.8 family",
971 "^ST3(400[68]32|300[68]31|250[68]23|200826)AS?$",
972 ".*",
973 NULL, NULL, NULL, NULL
974 },
975 { "Seagate Barracuda 7200.9 family",
976 "^ST3(500[68]41|400[68]33|300[68]22|250[68]24|250[68]24|200827|160[28]12|120814|120[28]13|80[28]110|402111)AS?$",
977 ".*",
978 NULL, NULL, NULL, NULL
979 },
980 { "Seagate Barracuda 7200.10 family",
981 "^ST3(750[68]4|500[68]3|400[68]2|320[68]2|300[68]2|250[68]2|20082)0AS?$",
982 ".*",
983 NULL, NULL, NULL, NULL
984 },
985 { "Seagate Medalist 17240, 13030, 10231, 8420, and 4310",
986 "^ST3(17240|13030|10231|8420|4310)A$",
987 ".*",
988 NULL, NULL, NULL, NULL
989 },
990 { "Seagate Medalist 17242, 13032, 10232, 8422, and 4312",
991 "^ST3(1724|1303|1023|842|431)2A$",
992 ".*",
993 NULL, NULL, NULL, NULL
994 },
995 { "Seagate NL35 family",
996 "^ST3(250623|250823|400632|400832|250824|250624|400633|400833|500641|500841)NS$",
997 ".*",
998 NULL, NULL, NULL, NULL
999 },
1000 { "Western Digital Protege",
1001 /* Western Digital drives with this comment all appear to use Attribute 9 in
1002 * a non-standard manner. These entries may need to be updated when it
1003 * is understood exactly how Attribute 9 should be interpreted.
1004 * UPDATE: this is probably explained by the WD firmware bug described in the
1005 * smartmontools FAQ */
1006 "^WDC WD([2468]00E|1[26]00A)B-.*$",
1007 ".*",
1008 NULL, NULL, NULL, NULL
1009 },
1010 { "Western Digital Caviar family",
1011 /* Western Digital drives with this comment all appear to use Attribute 9 in
1012 * a non-standard manner. These entries may need to be updated when it
1013 * is understood exactly how Attribute 9 should be interpreted.
1014 * UPDATE: this is probably explained by the WD firmware bug described in the
1015 * smartmontools FAQ */
1016 "^WDC WD(2|3|4|6|8|10|12|16|18|20|25)00BB-.*$",
1017 ".*",
1018 NULL, NULL, NULL, NULL
1019 },
1020 { "Western Digital Caviar WDxxxAB series",
1021 /* Western Digital drives with this comment all appear to use Attribute 9 in
1022 * a non-standard manner. These entries may need to be updated when it
1023 * is understood exactly how Attribute 9 should be interpreted.
1024 * UPDATE: this is probably explained by the WD firmware bug described in the
1025 * smartmontools FAQ */
1026 "^WDC WD(3|4|6)00AB-.*$",
1027 ".*",
1028 NULL, NULL, NULL, NULL
1029 },
1030 { "Western Digital Caviar WDxxxAA series",
1031 /* Western Digital drives with this comment all appear to use Attribute 9 in
1032 * a non-standard manner. These entries may need to be updated when it
1033 * is understood exactly how Attribute 9 should be interpreted.
1034 * UPDATE: this is probably explained by the WD firmware bug described in the
1035 * smartmontools FAQ */
1036 "^WDC WD...?AA(-.*)?$",
1037 ".*",
1038 NULL, NULL, NULL, NULL
1039 },
1040 { "Western Digital Caviar WDxxxBA series",
1041 /* Western Digital drives with this comment all appear to use Attribute 9 in
1042 * a non-standard manner. These entries may need to be updated when it
1043 * is understood exactly how Attribute 9 should be interpreted.
1044 * UPDATE: this is probably explained by the WD firmware bug described in the
1045 * smartmontools FAQ */
1046 "^WDC WD...BA$",
1047 ".*",
1048 NULL, NULL, NULL, NULL
1049 },
1050 { NULL, // Western Digital Caviar AC12500, AC14300, AC23200, AC24300, AC25100,
1051 // AC36400, AC38400
1052 "^WDC AC(125|143|232|243|251|364|384)00.?",
1053 ".*",
1054 NULL, NULL, NULL, NULL
1055 },
1056 { "Western Digital Caviar Serial ATA family",
1057 "^WDC WD(4|8|20|32)00BD-.*$",
1058 ".*",
1059 NULL, NULL, NULL, NULL
1060 },
1061 { "Western Digital Caviar SE family",
1062 /* Western Digital drives with this comment all appear to use Attribute 9 in
1063 * a non-standard manner. These entries may need to be updated when it
1064 * is understood exactly how Attribute 9 should be interpreted.
1065 * UPDATE: this is probably explained by the WD firmware bug described in the
1066 * smartmontools FAQ */
1067 "^WDC WD((4|6|8|10|12|16|18|20|25|30|32)00JB|(12|20|25)00PB)-.*$",
1068 ".*",
1069 NULL, NULL, NULL, NULL
1070 },
1071 { "Western Digital Caviar SE (Serial ATA) family",
1072 "^WDC WD((4|8|12|16|20|25|32)00JD|(12|16|20|25|30|32)00JS|1600AAJS)-.*$",
1073 ".*",
1074 NULL, NULL, NULL, NULL
1075 },
1076 { "Western Digital Caviar SE16 family",
1077 "^WDC WD((25|32|40|50)00KS|4000KD)-.*$",
1078 ".*",
1079 NULL, NULL, NULL, NULL
1080 },
1081 { "Western Digital Caviar RE Serial ATA series",
1082 "^WDC WD((12|16|25|32)00SD|2500YD|4000Y[RS]|5000YS)-.*$",
1083 ".*",
1084 NULL, NULL, NULL, NULL
1085 },
1086 { "Western Digital Raptor family",
1087 "^WDC WD((360|740|800)GD|(360|740|1500)ADFD)-.*$",
1088 ".*",
1089 NULL, NULL, NULL, NULL
1090 },
1091 { "Western Digital Scorpio family",
1092 "^WDC WD((12|10|8|6|4)00(UE|VE|BEAS|BEVS))-.*$",
1093 ".*",
1094 NULL, NULL, NULL, NULL
1095 },
1096 { NULL, // QUANTUM BIGFOOT TS10.0A
1097 "^QUANTUM BIGFOOT TS10.0A$",
1098 ".*",
1099 NULL, NULL, NULL, NULL
1100 },
1101 { NULL, // QUANTUM FIREBALLlct15 20 and QUANTUM FIREBALLlct15 30
1102 "^QUANTUM FIREBALLlct15 [123]0$",
1103 ".*",
1104 NULL, NULL, NULL, NULL
1105 },
1106 { "QUANTUM FIREBALLlct20 series",
1107 "^QUANTUM FIREBALLlct20 [234]0$",
1108 ".*",
1109 NULL, NULL, NULL, NULL
1110 },
1111 { NULL, // QUANTUM FIREBALL CX10.2A
1112 "^QUANTUM FIREBALL CX10.2A$",
1113 ".*",
1114 NULL, NULL, NULL, NULL
1115 },
1116 { "Quantum Fireball Plus LM series",
1117 "^QUANTUM FIREBALLP LM(10.2|15|20.5|30)$",
1118 ".*",
1119 NULL, NULL, NULL, NULL
1120 },
1121 { "Quantum Fireball CR series",
1122 "^QUANTUM FIREBALL CR(4.3|8.4)A$",
1123 ".*",
1124 NULL, NULL, NULL, NULL
1125 },
1126 { NULL, // QUANTUM FIREBALLP AS10.2, AS20.5, AS30.0, and AS40.0
1127 "^QUANTUM FIREBALLP AS(10.2|20.5|30.0|40.0)$",
1128 ".*",
1129 NULL, NULL, NULL, NULL
1130 },
1131 { NULL, // QUANTUM FIREBALL EX6.4A
1132 "^QUANTUM FIREBALL EX6.4A$",
1133 ".*",
1134 NULL, NULL, NULL, NULL
1135 },
1136 { NULL, // QUANTUM FIREBALL ST3.2A
1137 "^QUANTUM FIREBALL ST(3.2|4.3)A$",
1138 ".*",
1139 NULL, NULL, NULL, NULL
1140 },
1141 { NULL, // QUANTUM FIREBALL EX3.2A
1142 "^QUANTUM FIREBALL EX3.2A$",
1143 ".*",
1144 NULL, NULL, NULL, NULL
1145 },
1146 { NULL, // QUANTUM FIREBALLP KX27.3
1147 "^QUANTUM FIREBALLP KX27.3$",
1148 ".*",
1149 NULL, NULL, NULL, NULL
1150 },
1151 { "Quantum Fireball Plus KA series",
1152 "^QUANTUM FIREBALLP KA(9|10).1$",
1153 ".*",
1154 NULL, NULL, NULL, NULL
1155 },
1156 { "Quantum Fireball SE series",
1157 "^QUANTUM FIREBALL SE4.3A$",
1158 ".*",
1159 NULL, NULL, NULL, NULL
1160 },
1161 /*------------------------------------------------------------
1162 * End of table. Do not add entries below this marker.
1163 *------------------------------------------------------------ */
1164 {NULL, NULL, NULL, NULL, NULL, NULL, NULL}
1165 };
1166
1167 // Searches knowndrives[] for a drive with the given model number and firmware
1168 // string. If either the drive's model or firmware strings are not set by the
1169 // manufacturer then values of NULL may be used. Returns the index of the
1170 // first match in knowndrives[] or -1 if no match if found.
1171 int lookupdrive(const char *model, const char *firmware)
1172 {
1173 regex_t regex;
1174 int i, index;
1175 const char *empty = "";
1176
1177 model = model ? model : empty;
1178 firmware = firmware ? firmware : empty;
1179
1180 for (i = 0, index = -1; index == -1 && knowndrives[i].modelregexp; i++) {
1181 // Attempt to compile regular expression.
1182 if (compileregex(&regex, knowndrives[i].modelregexp, REG_EXTENDED))
1183 goto CONTINUE;
1184
1185 // Check whether model matches the regular expression in knowndrives[i].
1186 if (!regexec(&regex, model, 0, NULL, 0)) {
1187 // model matches, now check firmware.
1188 if (!knowndrives[i].firmwareregexp)
1189 // The firmware regular expression in knowndrives[i] is NULL, which is
1190 // considered a match.
1191 index = i;
1192 else {
1193 // Compare firmware against the regular expression in knowndrives[i].
1194 regfree(&regex); // Recycle regex.
1195 if (compileregex(&regex, knowndrives[i].firmwareregexp, REG_EXTENDED))
1196 goto CONTINUE;
1197 if (!regexec(&regex, firmware, 0, NULL, 0))
1198 index = i;
1199 }
1200 }
1201 CONTINUE:
1202 regfree(&regex);
1203 }
1204
1205 return index;
1206 }
1207
1208
1209 // Shows all presets for drives in knowndrives[].
1210 void showonepreset(const drivesettings *drivetable){
1211
1212 const unsigned char (* presets)[2] = drivetable->vendoropts;
1213 int first_preset = 1;
1214
1215 // Basic error check
1216 if (!drivetable || !drivetable->modelregexp){
1217 pout("Null known drive table pointer. Please report\n"
1218 "this error to smartmontools developers at " PACKAGE_BUGREPORT ".\n");
1219 return;
1220 }
1221
1222 // print model and firmware regular expressions
1223 pout("%-*s %s\n", TABLEPRINTWIDTH, "MODEL REGEXP:", drivetable->modelregexp);
1224 pout("%-*s %s\n", TABLEPRINTWIDTH, "FIRMWARE REGEXP:", drivetable->firmwareregexp ?
1225 drivetable->firmwareregexp : "");
1226 pout("%-*s %s\n", TABLEPRINTWIDTH, "MODEL FAMILY:", drivetable->modelfamily ?
1227 drivetable->modelfamily : "");
1228
1229 // if there are any presets, then show them
1230 if (presets && (*presets)[0]) while (1) {
1231 char out[256];
1232 const int attr = (*presets)[0], val = (*presets)[1];
1233 unsigned char fakearray[MAX_ATTRIBUTE_NUM];
1234
1235 // if we are at the end of the attribute list, break out
1236 if (!attr)
1237 break;
1238
1239 // This is a hack. ataPrintSmartAttribName() needs a pointer to an
1240 // "array" to dereference, so we provide such a pointer.
1241 fakearray[attr]=val;
1242 ataPrintSmartAttribName(out, attr, fakearray);
1243
1244 // Use leading zeros instead of spaces so that everything lines up.
1245 out[0] = (out[0] == ' ') ? '0' : out[0];
1246 out[1] = (out[1] == ' ') ? '0' : out[1];
1247 pout("%-*s %s\n", TABLEPRINTWIDTH, first_preset ? "ATTRIBUTE OPTIONS:" : "", out);
1248 first_preset = 0;
1249 presets++;
1250 }
1251 else
1252 pout("%-*s %s\n", TABLEPRINTWIDTH, "ATTRIBUTE OPTIONS:", "None preset; no -v options are required.");
1253
1254
1255 // Is a special purpose function defined? If so, describe it
1256 if (drivetable->specialpurpose){
1257 pout("%-*s ", TABLEPRINTWIDTH, "OTHER PRESETS:");
1258 pout("%s\n", drivetable->functiondesc ?
1259 drivetable->functiondesc : "A special purpose function "
1260 "is defined for this drive");
1261 }
1262
1263 // Print any special warnings
1264 if (drivetable->warningmsg){
1265 pout("%-*s ", TABLEPRINTWIDTH, "WARNINGS:");
1266 pout("%s\n", drivetable->warningmsg);
1267 }
1268
1269 return;
1270 }
1271
1272 // Shows all presets for drives in knowndrives[].
1273 // Returns <0 on syntax error in regular expressions.
1274 int showallpresets(void){
1275 int i;
1276 int rc = 0;
1277 regex_t regex;
1278
1279 // loop over all entries in the knowndrives[] table, printing them
1280 // out in a nice format
1281 for (i=0; knowndrives[i].modelregexp; i++){
1282 showonepreset(&knowndrives[i]);
1283 pout("\n");
1284 }
1285
1286 // Check all regular expressions
1287 for (i=0; knowndrives[i].modelregexp; i++){
1288 if (compileregex(&regex, knowndrives[i].modelregexp, REG_EXTENDED))
1289 rc = -1;
1290 if (knowndrives[i].firmwareregexp) {
1291 if (compileregex(&regex, knowndrives[i].firmwareregexp, REG_EXTENDED))
1292 rc = -1;
1293 }
1294 }
1295 pout("For information about adding a drive to the database see the FAQ on the\n");
1296 pout("smartmontools home page: " PACKAGE_HOMEPAGE "\n");
1297 return rc;
1298 }
1299
1300 // Shows all matching presets for a drive in knowndrives[].
1301 // Returns # matching entries.
1302 int showmatchingpresets(const char *model, const char *firmware){
1303 int i;
1304 int cnt = 0;
1305 const char * firmwaremsg = (firmware ? firmware : "(any)");
1306 regex_t regex;
1307
1308 for (i=0; knowndrives[i].modelregexp; i++){
1309 if (i > 0)
1310 regfree(&regex);
1311 if (compileregex(&regex, knowndrives[i].modelregexp, REG_EXTENDED))
1312 continue;
1313 if (regexec(&regex, model, 0, NULL, 0))
1314 continue;
1315 if (firmware && knowndrives[i].firmwareregexp) {
1316 regfree(&regex);
1317 if (compileregex(&regex, knowndrives[i].firmwareregexp, REG_EXTENDED))
1318 continue;
1319 if (regexec(&regex, firmware, 0, NULL, 0))
1320 continue;
1321 }
1322 if (++cnt == 1)
1323 pout("Drive found in smartmontools Database. Drive identity strings:\n"
1324 "%-*s %s\n"
1325 "%-*s %s\n"
1326 "match smartmontools Drive Database entry:\n",
1327 TABLEPRINTWIDTH, "MODEL:", model, TABLEPRINTWIDTH, "FIRMWARE:", firmwaremsg);
1328 else if (cnt == 2)
1329 pout("and match these additional entries:\n");
1330 showonepreset(&knowndrives[i]);
1331 pout("\n");
1332 }
1333 regfree(&regex);
1334 if (cnt == 0)
1335 pout("No presets are defined for this drive. Its identity strings:\n"
1336 "MODEL: %s\n"
1337 "FIRMWARE: %s\n"
1338 "do not match any of the known regular expressions.\n",
1339 model, firmwaremsg);
1340 return cnt;
1341 }
1342
1343 // Shows the presets (if any) that are available for the given drive.
1344 void showpresets(const struct ata_identify_device *drive){
1345 int i;
1346 char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1];
1347
1348 // get the drive's model/firmware strings
1349 format_ata_string(model, (char *)drive->model, MODEL_STRING_LENGTH);
1350 format_ata_string(firmware, (char *)drive->fw_rev, FIRMWARE_STRING_LENGTH);
1351
1352 // and search to see if they match values in the table
1353 if ((i = lookupdrive(model, firmware)) < 0) {
1354 // no matches found
1355 pout("No presets are defined for this drive. Its identity strings:\n"
1356 "MODEL: %s\n"
1357 "FIRMWARE: %s\n"
1358 "do not match any of the known regular expressions.\n"
1359 "Use -P showall to list all known regular expressions.\n",
1360 model, firmware);
1361 return;
1362 }
1363
1364 // We found a matching drive. Print out all information about it.
1365 pout("Drive found in smartmontools Database. Drive identity strings:\n"
1366 "%-*s %s\n"
1367 "%-*s %s\n"
1368 "match smartmontools Drive Database entry:\n",
1369 TABLEPRINTWIDTH, "MODEL:", model, TABLEPRINTWIDTH, "FIRMWARE:", firmware);
1370 showonepreset(&knowndrives[i]);
1371 return;
1372 }
1373
1374 // Sets preset vendor attribute options in opts by finding the entry
1375 // (if any) for the given drive in knowndrives[]. Values that have
1376 // already been set in opts will not be changed. Returns <0 if drive
1377 // not recognized else index >=0 into drive database.
1378 int applypresets(const struct ata_identify_device *drive, unsigned char **optsptr,
1379 smartmonctrl *con) {
1380 int i;
1381 unsigned char *opts;
1382 char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1];
1383
1384 if (*optsptr==NULL)
1385 bytes+=MAX_ATTRIBUTE_NUM;
1386
1387 if (*optsptr==NULL && !(*optsptr=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM,1))){
1388 pout("Unable to allocate memory in applypresets()");
1389 bytes-=MAX_ATTRIBUTE_NUM;
1390 EXIT(1);
1391 }
1392
1393 opts=*optsptr;
1394
1395 // get the drive's model/firmware strings
1396 format_ata_string(model, (char *)drive->model, MODEL_STRING_LENGTH);
1397 format_ata_string(firmware, (char *)drive->fw_rev, FIRMWARE_STRING_LENGTH);
1398
1399 // Look up the drive in knowndrives[].
1400 if ((i = lookupdrive(model, firmware)) >= 0) {
1401
1402 // if vendoropts is non-NULL then Attribute interpretation presets
1403 if (knowndrives[i].vendoropts) {
1404 const unsigned char (* presets)[2];
1405
1406 // For each attribute in list of attribute/val pairs...
1407 presets = knowndrives[i].vendoropts;
1408 while (1) {
1409 const int attr = (*presets)[0];
1410 const int val = (*presets)[1];
1411
1412 if (!attr)
1413 break;
1414
1415 // ... set attribute if user hasn't already done so.
1416 if (!opts[attr])
1417 opts[attr] = val;
1418 presets++;
1419 }
1420 }
1421
1422 // If a special-purpose function is defined for this drive then
1423 // call it. Note that if command line arguments or Directives
1424 // over-ride this choice, then the specialpurpose function that is
1425 // called must deal with this.
1426 if (knowndrives[i].specialpurpose)
1427 (*knowndrives[i].specialpurpose)(con);
1428 }
1429
1430 // return <0 if drive wasn't recognized, or index>=0 into database
1431 // if it was
1432 return i;
1433 }