]> git.proxmox.com Git - mirror_smartmontools-debian.git/blob - knowndrives.c
debian/rules: - remove autogenerated files
[mirror_smartmontools-debian.git] / knowndrives.c
1 /*
2 * knowndrives.c
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-6 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.c,v 1.139 2006/04/05 19:50:07 chrfranke 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.c 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
115 const char may_need_minus_F_disabled[] ="May need -F samsung disabled; see manual for details.";
116 const char may_need_minus_F2_disabled[]="May need -F samsung2 disabled; see manual for details.";
117 const char may_need_minus_F2_enabled[] ="May need -F samsung2 enabled; see manual for details.";
118 const char may_need_minus_F_enabled[] ="May need -F samsung or -F samsung2 enabled; see manual for details.";
119
120 /* Special-purpose functions for use in knowndrives[]. */
121 void specialpurpose_reverse_samsung(smartmonctrl *con)
122 {
123 if (con->fixfirmwarebug==FIX_NOTSPECIFIED)
124 con->fixfirmwarebug = FIX_SAMSUNG;
125 }
126 void specialpurpose_reverse_samsung2(smartmonctrl *con)
127 {
128 if (con->fixfirmwarebug==FIX_NOTSPECIFIED)
129 con->fixfirmwarebug = FIX_SAMSUNG2;
130 }
131
132 /* Table of settings for known drives terminated by an element containing all
133 * zeros. The drivesettings structure is described in knowndrives.h. Note
134 * that lookupdrive() will search knowndrives[] from the start to end or
135 * until it finds the first match, so the order in knowndrives[] is important
136 * for distinct entries that could match the same drive. */
137
138 // Note that the table just below uses EXTENDED REGULAR EXPRESSIONS.
139 // A good on-line reference for these is:
140 // http://www.zeus.com/extra/docsystem/docroot/apps/web/docs/modules/access/regex.html
141
142 const drivesettings knowndrives[] = {
143 { "IBM Deskstar 60GXP series", // ER60A46A firmware
144 "(IBM-|Hitachi )?IC35L0[12346]0AVER07",
145 "^ER60A46A$",
146 NULL, NULL, NULL, NULL
147 },
148 { "IBM Deskstar 60GXP series", // All other firmware
149 "(IBM-|Hitachi )?IC35L0[12346]0AVER07",
150 ".*",
151 "IBM Deskstar 60GXP drives may need upgraded SMART firmware.\n"
152 "Please see http://www.geocities.com/dtla_update/index.html#rel and\n"
153 "http://www-3.ibm.com/pc/support/site.wss/document.do?lndocid=MIGR-42215 or\n"
154 "http://www-1.ibm.com/support/docview.wss?uid=psg1MIGR-42215",
155 NULL, NULL, NULL
156 },
157 { "IBM Deskstar 40GV & 75GXP series (A5AA/A6AA firmware)",
158 "(IBM-)?DTLA-30[57]0[123467][05]",
159 "^T[WX][123468AG][OF]A[56]AA$",
160 NULL, NULL, NULL, NULL
161 },
162 { "IBM Deskstar 40GV & 75GXP series (all other firmware)",
163 "(IBM-)?DTLA-30[57]0[123467][05]",
164 ".*",
165 "IBM Deskstar 40GV and 75GXP drives may need upgraded SMART firmware.\n"
166 "Please see http://www.geocities.com/dtla_update/ and\n"
167 "http://www-3.ibm.com/pc/support/site.wss/document.do?lndocid=MIGR-42215 or\n"
168 "http://www-1.ibm.com/support/docview.wss?uid=psg1MIGR-42215",
169 NULL, NULL, NULL
170 },
171 { NULL, // ExcelStor J240, J340, J360, J680, and J880
172 "^ExcelStor Technology J(24|34|36|68|88)0$",
173 ".*",
174 NULL, NULL, NULL, NULL
175 },
176 { NULL, // Fujitsu M1623TAU
177 "^FUJITSU M1623TAU$",
178 ".*",
179 NULL,
180 vendoropts_9_seconds,
181 NULL, NULL
182 },
183 { "Fujitsu MHG and MHH series",
184 "^FUJITSU MH(G2102|H20(64|48|32))AT$",
185 ".*",
186 NULL,
187 vendoropts_9_seconds,
188 NULL, NULL
189 },
190 { "Fujitsu MHJ and MHK series",
191 "^FUJITSU MH[JK]....ATU?$",
192 ".*",
193 NULL,
194 vendoropts_9_seconds,
195 NULL, NULL
196 },
197 { "Fujitsu MPB series",
198 "^FUJITSU MPB....ATU?$",
199 ".*",
200 NULL,
201 vendoropts_9_seconds,
202 NULL, NULL
203 },
204 { "Fujitsu MPD and MPE series",
205 "^FUJITSU MP[DE]....A[HTE]$",
206 ".*",
207 NULL,
208 vendoropts_9_seconds,
209 NULL, NULL
210 },
211 { "Fujitsu MPF series",
212 "^FUJITSU MPF3(102A[HT]|153A[HT]|204A[HT])$",
213 ".*",
214 NULL,
215 vendoropts_9_seconds,
216 NULL, NULL
217 },
218 { "Fujitsu MPG series",
219 "^FUJITSU MPG3(102A(H|T E)|153AH|204A(H|[HT] E)|307A(H E|T)|409A[HT] E)$",
220 ".*",
221 NULL,
222 vendoropts_9_seconds,
223 NULL, NULL
224 },
225 { "Fujitsu MPC series",
226 "^FUJITSU MPC3(032AT|043AT|045AH|064A[HT]|084AT|096AT|102AT)$",
227 ".*",
228 NULL,
229 vendoropts_9_seconds,
230 NULL, NULL
231 },
232 { NULL, // Fujitsu MHN2300AT
233 "^FUJITSU MHN2300AT$",
234 ".*",
235 NULL,
236 vendoropts_9_seconds,
237 NULL, NULL
238 },
239 { NULL, // Fujitsu MHR2040AT
240 "^FUJITSU MHR2040AT$",
241 ".*", // Tested on 40BA
242 NULL,
243 vendoropts_Fujitsu_MHR2040AT,
244 NULL, NULL
245 },
246 { NULL, // Fujitsu MHR2020AT
247 "^FUJITSU MHR2020AT$",
248 ".*",
249 NULL,
250 vendoropts_9_seconds,
251 NULL, NULL
252 },
253 { "Fujitsu MHSxxxxAT family",
254 "^FUJITSU MHS20[6432]0AT( .)?$",
255 ".*",
256 NULL,
257 vendoropts_Fujitsu_MHS2020AT,
258 NULL, NULL
259 },
260 { NULL, // Fujitsu MHL2300AT, MHM2200AT, MHM2100AT, MHM2150AT
261 "^FUJITSU MH(L230|M2(20|10|15))0AT$",
262 ".*",
263 "This drive's firmware has a harmless Drive Identity Structure\n"
264 "checksum error bug.",
265 vendoropts_9_seconds,
266 NULL, NULL
267 },
268 { "Fujitsu MHT2xxxAT/MHU2100AT series",
269 "^FUJITSU MH(T20[23468]0AT( PL)?|U2100AT)$",
270 ".*",
271 NULL,
272 vendoropts_9_seconds,
273 NULL, NULL
274 },
275 { "Fujitsu MHTxxxxAH family",
276 "^FUJITSU MHT20[468]0AH$",
277 ".*",
278 NULL,
279 vendoropts_9_seconds,
280 NULL, NULL
281 },
282 { NULL, // Samsung SV4012H (known firmware)
283 "^SAMSUNG SV4012H$",
284 "^RM100-08$",
285 NULL,
286 vendoropts_Samsung_SV4012H,
287 specialpurpose_reverse_samsung,
288 same_as_minus_F
289 },
290 { NULL, // Samsung SV4012H (all other firmware)
291 "^SAMSUNG SV4012H$",
292 ".*",
293 may_need_minus_F_disabled,
294 vendoropts_Samsung_SV4012H,
295 specialpurpose_reverse_samsung,
296 same_as_minus_F
297 },
298 { NULL, // Samsung SV0412H (known firmware)
299 "^SAMSUNG SV0412H$",
300 "^SK100-01$",
301 NULL,
302 vendoropts_Samsung_SV1204H,
303 specialpurpose_reverse_samsung,
304 same_as_minus_F
305 },
306 { NULL, // Samsung SV0412H (all other firmware)
307 "^SAMSUNG SV0412H$",
308 ".*",
309 may_need_minus_F_disabled,
310 vendoropts_Samsung_SV1204H,
311 specialpurpose_reverse_samsung,
312 same_as_minus_F
313 },
314 { NULL, // Samsung SV1204H (known firmware)
315 "^SAMSUNG SV1204H$",
316 "^RK100-1[3-5]$",
317 NULL,
318 vendoropts_Samsung_SV1204H,
319 specialpurpose_reverse_samsung,
320 same_as_minus_F
321 },
322 { NULL, // Samsung SV1204H (all other firmware)
323 "^SAMSUNG SV1204H$",
324 ".*",
325 may_need_minus_F_disabled,
326 vendoropts_Samsung_SV1204H,
327 specialpurpose_reverse_samsung,
328 same_as_minus_F
329 },
330 { NULL, // SAMSUNG SV0322A tested with FW JK200-35
331 "^SAMSUNG SV0322A$",
332 ".*",
333 NULL,
334 NULL,
335 NULL,
336 NULL
337 },
338 { NULL, // SAMSUNG SP40A2H with RR100-07 firmware
339 "^SAMSUNG SP40A2H$",
340 "^RR100-07$",
341 NULL,
342 vendoropts_9_halfminutes,
343 specialpurpose_reverse_samsung,
344 same_as_minus_F
345 },
346 {
347 NULL, // Any other Samsung disk with *-23 *-24 firmware
348 // SAMSUNG SP1213N (TL100-23 firmware)
349 // SAMSUNG SP0802N (TK100-23 firmware)
350 // Samsung SP1604N, tested with FW TM100-23 and TM100-24
351 "^SAMSUNG .*$",
352 ".*-2[34]$",
353 NULL,
354 vendoropts_Samsung_SV4012H,
355 specialpurpose_reverse_samsung2,
356 same_as_minus_F2
357 },
358 { NULL, // All Samsung drives with '.*-25' firmware
359 "^SAMSUNG.*",
360 ".*-25$",
361 may_need_minus_F2_disabled,
362 vendoropts_Samsung_SV4012H,
363 specialpurpose_reverse_samsung2,
364 same_as_minus_F2
365 },
366 { NULL, // All Samsung drives with '.*-26 or later (currently to -39)' firmware
367 "^SAMSUNG.*",
368 ".*-(2[6789]|3[0-9])$",
369 NULL,
370 vendoropts_Samsung_SV4012H,
371 NULL,
372 NULL
373 },
374 { NULL, // Samsung ALL OTHER DRIVES
375 "^SAMSUNG.*",
376 ".*",
377 may_need_minus_F_enabled,
378 NULL, NULL, NULL
379 },
380 { "Maxtor Fireball 541DX family",
381 "^Maxtor 2B0(0[468]|1[05]|20)H1$",
382 ".*",
383 NULL,
384 vendoropts_Maxtor_4D080H4,
385 NULL, NULL
386 },
387 { "Maxtor Fireball 3 family",
388 "^Maxtor 2F0[234]0[JL]0$",
389 ".*",
390 NULL,
391 vendoropts_9_minutes,
392 NULL, NULL
393 },
394 { "Maxtor DiamondMax 2160 Ultra ATA family",
395 "^Maxtor 8(2160D2|3228D3|3240D3|4320D4|6480D6|8400D8|8455D8)$",
396 ".*",
397 NULL,
398 vendoropts_9_minutes,
399 NULL, NULL
400 },
401 { "Maxtor DiamondMax 2880 Ultra ATA family",
402 "^Maxtor 9(0510D4|0576D4|0648D5|0720D5|0840D6|0845D6|0864D6|1008D7|1080D8|1152D8)$",
403 ".*",
404 NULL,
405 vendoropts_9_minutes,
406 NULL, NULL
407 },
408 { "Maxtor DiamondMax 3400 Ultra ATA family",
409 "^Maxtor 9(1(360|350|202)D8|1190D7|10[12]0D6|0840D5|06[48]0D4|0510D3|1(350|202)E8|1010E6|0840E5|0640E4)$",
410 ".*",
411 NULL,
412 vendoropts_9_minutes,
413 NULL, NULL
414 },
415 { "Maxtor DiamondMax D540X-4G family",
416 "^Maxtor 4G(120J6|160J[68])$",
417 ".*",
418 NULL,
419 vendoropts_Maxtor_4D080H4,
420 NULL, NULL
421 },
422 { "Maxtor DiamondMax D540X-4K family",
423 "^MAXTOR 4K(020H1|040H2|060H3|080H4)$",
424 ".*",
425 NULL, NULL, NULL, NULL
426 },
427 { "Maxtor DiamondMax Plus D740X family",
428 "^MAXTOR 6L0(20[JL]1|40[JL]2|60[JL]3|80[JL]4)$",
429 ".*",
430 NULL, NULL, NULL, NULL
431 },
432 { "Maxtor DiamondMax Plus 5120 Ultra ATA 33 family",
433 "^Maxtor 9(0512D2|0680D3|0750D3|0913D4|1024D4|1360D6|1536D6|1792D7|2048D8)$",
434 ".*",
435 NULL,
436 vendoropts_9_minutes,
437 NULL, NULL
438 },
439 { "Maxtor DiamondMax Plus 6800 Ultra ATA 66 family",
440 "^Maxtor 9(2732U8|2390U7|2049U6|1707U5|1366U4|1024U3|0845U3|0683U2)$",
441 ".*",
442 NULL,
443 vendoropts_9_minutes,
444 NULL, NULL
445 },
446 { "Maxtor DiamondMax D540X-4D",
447 "^Maxtor 4D0(20H1|40H2|60H3|80H4)$",
448 ".*",
449 NULL,
450 vendoropts_Maxtor_4D080H4,
451 NULL, NULL
452 },
453 { "Maxtor DiamondMax 16 family",
454 "^Maxtor 4(R0[68]0[JL]0|R1[26]0L0|A160J0|R120L4)$",
455 ".*",
456 NULL,
457 vendoropts_9_minutes,
458 NULL, NULL
459 },
460 { "Maxtor DiamondMax 4320 family",
461 "^Maxtor (91728D8|91512D7|91303D6|91080D5|90845D4|90645D3|90648D4|90432D2)$",
462 ".*",
463 NULL,
464 vendoropts_9_minutes,
465 NULL, NULL
466 },
467 { "Maxtor DiamondMax 17 VL family",
468 "^Maxtor 9(0431U1|0641U2|0871U2|1301U3|1741U4)$",
469 ".*",
470 NULL,
471 vendoropts_9_minutes,
472 NULL, NULL
473 },
474 { "Maxtor DiamondMax 20 VL family",
475 "^Maxtor (94091U8|93071U6|92561U5|92041U4|91731U4|91531U3|91361U3|91021U2|90841U2|90651U2)$",
476 ".*",
477 NULL,
478 vendoropts_9_minutes,
479 NULL, NULL
480 },
481 { "Maxtor DiamondMax VL 30 family",
482 "^Maxtor (33073U4|32049U3|31536U2|30768U1)$",
483 ".*",
484 NULL,
485 vendoropts_9_minutes,
486 NULL, NULL
487 },
488 { "Maxtor DiamondMax 36 family",
489 "^Maxtor (93652U8|92739U6|91826U4|91369U3|90913U2|90845U2|90435U1)$",
490 ".*",
491 NULL,
492 vendoropts_9_minutes,
493 NULL, NULL
494 },
495 { "Maxtor DiamondMax 40 ATA 66 series",
496 "^Maxtor 9(0684U2|1024U2|1362U3|1536U3|2049U4|2562U5|3073U6|4098U8)$",
497 ".*",
498 NULL,
499 vendoropts_9_minutes,
500 NULL, NULL
501 },
502 { "Maxtor DiamondMax Plus 40 series (Ultra ATA 66 and Ultra ATA 100)",
503 "^Maxtor (54098[UH]8|53073[UH]6|52732[UH]6|52049[UH]4|51536[UH]3|51369[UH]3|51024[UH]2)$",
504 ".*",
505 NULL,
506 vendoropts_9_minutes,
507 NULL, NULL
508 },
509 { "Maxtor DiamondMax 40 VL Ultra ATA 100 series",
510 "^Maxtor 3(1024H1|1535H2|2049H2|3073H3|4098H4)( B)?$",
511 ".*",
512 NULL,
513 vendoropts_9_minutes,
514 NULL, NULL
515 },
516 { "Maxtor DiamondMax Plus 45 Ulta ATA 100 family",
517 "^Maxtor 5(4610H6|4098H6|3073H4|2049H3|1536H2|1369H2|1023H2)$",
518 ".*",
519 NULL,
520 vendoropts_9_minutes,
521 NULL, NULL
522 },
523 { "Maxtor DiamondMax Plus 60 family",
524 "^Maxtor 5T0(60H6|40H4|30H3|20H2|10H1)$",
525 ".*",
526 NULL,
527 vendoropts_9_minutes,
528 NULL, NULL
529 },
530 { "Maxtor DiamondMax 80 family",
531 "^Maxtor (98196H8|96147H6)$",
532 ".*",
533 NULL,
534 vendoropts_9_minutes,
535 NULL, NULL
536 },
537 { "Maxtor DiamondMax 536DX family",
538 "^Maxtor 4W(100H6|080H6|060H4|040H3|030H2)$",
539 ".*",
540 NULL,
541 vendoropts_9_minutes,
542 NULL, NULL
543 },
544 { "Maxtor DiamondMax Plus 8 family",
545 "^Maxtor 6E0[234]0L0$",
546 ".*",
547 NULL,
548 vendoropts_9_minutes,
549 NULL, NULL
550 },
551 { "Maxtor DiamondMax 10 family",
552 "^Maxtor 6(B(30|25|20|16|12|08)0[MPRS]|L(100P|120[MP]|160M|200[MPRS]|250[RS]|300[RS]))0$",
553 ".*",
554 NULL,
555 vendoropts_9_minutes,
556 NULL, NULL
557 },
558 { "Maxtor DiamondMax Plus 9 family",
559 "^Maxtor 6Y((060|080|120|160)L0|(060|080|120|160|200|250)P0|(060|080|120|160|200|250)M0)$",
560 ".*",
561 NULL,
562 vendoropts_9_minutes,
563 NULL, NULL
564 },
565 { "Maxtor MaXLine Plus II",
566 "^Maxtor 7Y250[PM]0$",
567 ".*",
568 NULL,
569 vendoropts_9_minutes,
570 NULL, NULL
571 },
572 { "Maxtor MaXLine II family",
573 "^Maxtor [45]A(25|30|32)0[JN]0$",
574 ".*",
575 NULL,
576 vendoropts_9_minutes,
577 NULL, NULL
578 },
579 { NULL, // HITACHI_DK14FA-20B
580 "^HITACHI_DK14FA-20B$",
581 ".*",
582 NULL,
583 vendoropts_Hitachi_DK23XX,
584 NULL, NULL
585 },
586 { "HITACHI Travelstar DK23XX/DK23XXB series",
587 "^HITACHI_DK23..-..B?$",
588 ".*",
589 NULL,
590 vendoropts_Hitachi_DK23XX,
591 NULL, NULL
592 },
593 { "Hitachi Endurastar J4K20/N4K20 (formerly DK23FA-20J)",
594 "^(HITACHI_DK23FA-20J|HTA422020F9AT[JN]0)$",
595 ".*",
596 NULL,
597 vendoropts_Hitachi_DK23XX,
598 NULL, NULL
599 },
600 { "IBM Deskstar 14GXP and 16GP series",
601 "^IBM-DTTA-3(7101|7129|7144|5032|5043|5064|5084|5101|5129|5168)0$",
602 ".*",
603 NULL, NULL, NULL, NULL
604 },
605 { "IBM Deskstar 25GP and 22GXP family",
606 "^IBM-DJNA-3(5(101|152|203|250)|7(091|135|180|220))0$",
607 ".*",
608 NULL, NULL, NULL, NULL
609 },
610 { "IBM Travelstar 25GS, 18GT, and 12GN family",
611 "^IBM-DARA-2(25|18|15|12|09|06)000$",
612 ".*",
613 NULL, NULL, NULL, NULL
614 },
615 { "IBM Travelstar 48GH, 30GN, and 15GN family",
616 "^(IBM-|Hitachi )?IC25(T048ATDA05|N0(30|20|15|12|10|07|06|05)ATDA04)-.$",
617 ".*",
618 NULL, NULL, NULL, NULL
619 },
620 { "IBM Travelstar 32GH, 30GT, and 20GN family",
621 "^IBM-DJSA-2(32|30|20|10|05)$",
622 ".*",
623 NULL, NULL, NULL, NULL
624 },
625 { "IBM Deskstar 37GP and 34GXP family",
626 "^IBM-DPTA-3(5(375|300|225|150)|7(342|273|205|136))0$",
627 ".*",
628 NULL, NULL, NULL, NULL
629 },
630 { "IBM/Hitachi Travelstar 60GH and 40GN family",
631 "^(IBM-|Hitachi )?IC25(T060ATC[SX]05|N0[4321]0ATC[SX]04)-.$",
632 ".*",
633 NULL, NULL, NULL, NULL
634 },
635 { "IBM/Hitachi Travelstar 40GNX family",
636 "^(IBM-|Hitachi )?IC25N0[42]0ATC[SX]05-.$",
637 ".*",
638 NULL, NULL, NULL, NULL
639 },
640 { "Hitachi Travelstar 80GN family",
641 "^(Hitachi )?IC25N0[23468]0ATMR04-.$",
642 ".*",
643 NULL, NULL, NULL, NULL
644 },
645 { "Hitachi Travelstar 5K80 family",
646 "^HTS5480[8642]0M9AT00$",
647 ".*",
648 NULL, NULL, NULL, NULL
649 },
650 { "Hitachi Travelstar 5K100 series",
651 "^HTS5410[1864]0G9(AT|SA)00$",
652 ".*",
653 NULL, NULL, NULL, NULL
654 },
655 { "Hitachi Travelstar 7K60",
656 "^HTS726060M9AT00$",
657 ".*",
658 NULL, NULL, NULL, NULL
659 },
660 { "Hitachi Travelstar E7K60 family",
661 "^HTE7260[46]0M9AT00$",
662 ".*",
663 NULL, NULL, NULL, NULL
664 },
665 { "IBM/Hitachi Deskstar 120GXP family",
666 "^(IBM-)?IC35L((020|040|060|080|120)AVVA|0[24]0AVVN)07-[01]$",
667 ".*",
668 NULL, NULL, NULL, NULL
669 },
670 { "IBM/Hitachi Deskstar GXP-180 family",
671 "^(IBM-)?IC35L(030|060|090|120|180)AVV207-[01]$",
672 ".*",
673 NULL, NULL, NULL, NULL
674 },
675 { "IBM Travelstar 14GS",
676 "^IBM-DCYA-214000$",
677 ".*",
678 NULL, NULL, NULL, NULL
679 },
680 { "IBM Travelstar 4LP",
681 "^IBM-DTNA-2(180|216)0$",
682 ".*",
683 NULL, NULL, NULL, NULL
684 },
685 { "Hitachi Deskstar 7K80 series",
686 "^(Hitachi )?HDS7280([48]0PLAT20|(40)?PLA320)$",
687 ".*",
688 NULL, NULL, NULL, NULL
689 },
690 { "Hitachi Deskstar 7K250 series",
691 "^(Hitachi )?HDS7225((40|80|12|16)VLAT20|(12|16|25)VLAT80|(80|12|16|25)VLSA80)$",
692 ".*",
693 NULL, NULL, NULL, NULL
694 },
695 { "Hitachi Deskstar 7K400 series",
696 "^(Hitachi )?HDS724040KL(AT|SA)80$",
697 ".*",
698 NULL, NULL, NULL, NULL
699 },
700 { NULL, // TOSHIBA MK4025GAS
701 "^TOSHIBA MK4025GAS$",
702 ".*",
703 NULL, NULL, NULL, NULL
704 },
705 { "Toshiba 2.5\" HDD series", // TOSHIBA MK6021GAS [Bruce -- use for testing on laptop]
706 "^TOSHIBA MK6021GAS$",
707 ".*",
708 NULL, NULL, NULL, NULL
709 },
710 { NULL, // TOSHIBA MK6022GAX
711 "^TOSHIBA MK6022GAX$",
712 ".*",
713 NULL, NULL, NULL, NULL
714 },
715 { NULL, // TOSHIBA MK4019GAX/MK4019GAXB
716 "^TOSHIBA MK4019GAXB?$",
717 ".*",
718 NULL, NULL, NULL, NULL
719 },
720 { NULL, // TOSHIBA MK6409MAV
721 "^TOSHIBA MK6409MAV$",
722 ".*",
723 NULL, NULL, NULL, NULL
724 },
725 { NULL, // TOS MK3019GAXB SUN30G
726 "^TOS MK3019GAXB SUN30G$",
727 ".*",
728 NULL, NULL, NULL, NULL
729 },
730 { NULL, // TOSHIBA MK2016GAP, MK2017GAP, MK2018GAP, MK2018GAS, MK2023GAS
731 "^TOSHIBA MK20(1[678]GAP|(18|23)GAS)$",
732 ".*",
733 NULL, NULL, NULL, NULL
734 },
735 { NULL, // TOSHIBA MK4018GAS, MK4018GAP
736 "^TOSHIBA MK4018GA[SP]$",
737 ".*",
738 NULL, NULL, NULL, NULL
739 },
740 { NULL, // TOSHIBA MK3017GAP
741 "^TOSHIBA MK3017GAP$",
742 ".*",
743 NULL, NULL, NULL, NULL
744 },
745 { NULL, // TOSHIBA MK8026GAX
746 "^TOSHIBA MK8026GAX$",
747 ".*",
748 NULL, NULL, NULL, NULL
749 },
750 { "Seagate Momentus family",
751 "^ST9(20|28|40|48)11A$",
752 ".*",
753 NULL, NULL, NULL, NULL
754 },
755 { "Seagate Momentus 4200.2 Series",
756 "^ST9(100822|808210|60821|50212|402113|30219)A$",
757 ".*",
758 NULL, NULL, NULL, NULL
759 },
760 { "Seagate Momentus 5400.2 series",
761 "^ST9(100823|808211|60822|408114|308110)A$",
762 ".*",
763 NULL, NULL, NULL, NULL
764 },
765 { "Seagate Medalist 8641 family",
766 "^ST3(2110|3221|4312|6531|8641)A$",
767 ".*",
768 NULL, NULL, NULL, NULL
769 },
770 { "Seagate U Series X family",
771 "^ST3(10014A(CE)?|20014A)$",
772 ".*",
773 NULL, NULL, NULL, NULL
774 },
775 { "Seagate U Series 6 family",
776 "^ST3(8002|6002|4081|3061|2041)0A$",
777 ".*",
778 NULL, NULL, NULL, NULL
779 },
780 { "Seagate U Series 5 family",
781 "^ST3(40823|30621|20413|15311|10211)A$",
782 ".*",
783 NULL, NULL, NULL, NULL
784 },
785 { "Seagate U4 family",
786 "^ST3(2112|4311|6421|8421)A$",
787 ".*",
788 NULL, NULL, NULL, NULL
789 },
790 { "Seagate U8 family",
791 "^ST3(8410|4313|17221|13021)A$",
792 ".*",
793 NULL, NULL, NULL, NULL
794 },
795 { "Seagate U10 family",
796 "^ST3(20423|15323|10212)A$",
797 ".*",
798 NULL, NULL, NULL, NULL
799 },
800 { "Seagate Barracuda ATA II family",
801 "^ST3(3063|2042|1532|1021)0A$",
802 ".*",
803 NULL, NULL, NULL, NULL
804 },
805 { "Seagate Barracuda ATA III family",
806 "^ST3(40824|30620|20414|15310|10215)A$",
807 ".*",
808 NULL, NULL, NULL, NULL
809 },
810 { "Seagate Barracuda ATA IV family",
811 "^ST3(20011|30011|40016|60021|80021)A$",
812 ".*",
813 NULL, NULL, NULL, NULL
814 },
815 { "Seagate Barracuda ATA V family",
816 "^ST3(12002(3A|4A|9A|3AS)|800(23A|15A|23AS)|60(015A|210A)|40017A)$",
817 ".*",
818 NULL, NULL, NULL, NULL
819 },
820 { "Seagate Barracuda 5400.1",
821 "^ST340015A$",
822 ".*",
823 NULL, NULL, NULL, NULL
824 },
825 { "Seagate Barracuda 7200.7 and 7200.7 Plus family",
826 "^ST3(200021A|200822AS?|16002[13]AS?|12002[26]AS?|1[26]0827AS|8001[13]AS?|80817AS|60014A|40014AS?)$",
827 ".*",
828 NULL, NULL, NULL, NULL
829 },
830 { "Seagate Barracuda 7200.8 family",
831 "^ST3(400832|300831|250823|200826)AS?$",
832 ".*",
833 NULL, NULL, NULL, NULL
834 },
835 { "Seagate Medalist 17240, 13030, 10231, 8420, and 4310",
836 "^ST3(17240|13030|10231|8420|4310)A$",
837 ".*",
838 NULL, NULL, NULL, NULL
839 },
840 { "Seagate Medalist 17242, 13032, 10232, 8422, and 4312",
841 "^ST3(1724|1303|1023|842|431)2A$",
842 ".*",
843 NULL, NULL, NULL, NULL
844 },
845 { "Western Digital Protege",
846 /* Western Digital drives with this comment all appear to use Attribute 9 in
847 * a non-standard manner. These entries may need to be updated when it
848 * is understood exactly how Attribute 9 should be interpreted.
849 * UPDATE: this is probably explained by the WD firmware bug described in the
850 * smartmontools FAQ */
851 "^WDC WD([2468]00E|1[26]00A)B-.*$",
852 ".*",
853 NULL, NULL, NULL, NULL
854 },
855 { "Western Digital Caviar family",
856 /* Western Digital drives with this comment all appear to use Attribute 9 in
857 * a non-standard manner. These entries may need to be updated when it
858 * is understood exactly how Attribute 9 should be interpreted.
859 * UPDATE: this is probably explained by the WD firmware bug described in the
860 * smartmontools FAQ */
861 "^WDC WD(2|3|4|6|8|10|12|16|18|20|25)00BB-.*$",
862 ".*",
863 NULL, NULL, NULL, NULL
864 },
865 { "Western Digital Caviar WDxxxAB series",
866 /* Western Digital drives with this comment all appear to use Attribute 9 in
867 * a non-standard manner. These entries may need to be updated when it
868 * is understood exactly how Attribute 9 should be interpreted.
869 * UPDATE: this is probably explained by the WD firmware bug described in the
870 * smartmontools FAQ */
871 "^WDC WD(3|4|6)00AB-.*$",
872 ".*",
873 NULL, NULL, NULL, NULL
874 },
875 { "Western Digital Caviar WDxxxAA series",
876 /* Western Digital drives with this comment all appear to use Attribute 9 in
877 * a non-standard manner. These entries may need to be updated when it
878 * is understood exactly how Attribute 9 should be interpreted.
879 * UPDATE: this is probably explained by the WD firmware bug described in the
880 * smartmontools FAQ */
881 "^WDC WD...?AA(-.*)?$",
882 ".*",
883 NULL, NULL, NULL, NULL
884 },
885 { "Western Digital Caviar WDxxxBA series",
886 /* Western Digital drives with this comment all appear to use Attribute 9 in
887 * a non-standard manner. These entries may need to be updated when it
888 * is understood exactly how Attribute 9 should be interpreted.
889 * UPDATE: this is probably explained by the WD firmware bug described in the
890 * smartmontools FAQ */
891 "^WDC WD...BA$",
892 ".*",
893 NULL, NULL, NULL, NULL
894 },
895 { NULL, // Western Digital Caviar AC12500, AC14300, AC23200, AC24300, AC25100,
896 // AC36400, AC38400
897 "^WDC AC(125|143|232|243|251|364|384)00.?",
898 ".*",
899 NULL, NULL, NULL, NULL
900 },
901 { "Western Digital Caviar SE family",
902 /* Western Digital drives with this comment all appear to use Attribute 9 in
903 * a non-standard manner. These entries may need to be updated when it
904 * is understood exactly how Attribute 9 should be interpreted.
905 * UPDATE: this is probably explained by the WD firmware bug described in the
906 * smartmontools FAQ */
907 "^WDC WD((4|6|8|10|12|16|18|20|25|30|32)00JB|(12|20|25)00PB)-.*$",
908 ".*",
909 NULL, NULL, NULL, NULL
910 },
911 { "Western Digital Caviar SE (Serial ATA) family",
912 "^WDC WD(4|8|12|16|20|25)00JD-.*$",
913 ".*",
914 NULL, NULL, NULL, NULL
915 },
916 { "Western Digital Caviar RE Serial ATA series",
917 "^WDC WD((12|16|25|32)00SD|4000YR)-.*$",
918 ".*",
919 NULL, NULL, NULL, NULL
920 },
921 { "Western Digital Raptor family",
922 "^WDC WD(360|740)GD",
923 ".*",
924 NULL, NULL, NULL, NULL
925 },
926 { NULL, // QUANTUM BIGFOOT TS10.0A
927 "^QUANTUM BIGFOOT TS10.0A$",
928 ".*",
929 NULL, NULL, NULL, NULL
930 },
931 { NULL, // QUANTUM FIREBALLlct15 20 and QUANTUM FIREBALLlct15 30
932 "^QUANTUM FIREBALLlct15 [23]0$",
933 ".*",
934 NULL, NULL, NULL, NULL
935 },
936 { "QUANTUM FIREBALLlct20 series",
937 "^QUANTUM FIREBALLlct20 [234]0$",
938 ".*",
939 NULL, NULL, NULL, NULL
940 },
941 { NULL, // QUANTUM FIREBALL CX10.2A
942 "^QUANTUM FIREBALL CX10.2A$",
943 ".*",
944 NULL, NULL, NULL, NULL
945 },
946 { "Quantum Fireball Plus LM series",
947 "^QUANTUM FIREBALLP LM(10.2|15|20.5|30)$",
948 ".*",
949 NULL, NULL, NULL, NULL
950 },
951 { "Quantum Fireball CR series",
952 "^QUANTUM FIREBALL CR(4.3|8.4)A$",
953 ".*",
954 NULL, NULL, NULL, NULL
955 },
956 { NULL, // QUANTUM FIREBALLP AS10.2, AS20.5, and AS40.0
957 "^QUANTUM FIREBALLP AS(10.2|20.5|40.0)$",
958 ".*",
959 NULL, NULL, NULL, NULL
960 },
961 { NULL, // QUANTUM FIREBALL EX6.4A
962 "^QUANTUM FIREBALL EX6.4A$",
963 ".*",
964 NULL, NULL, NULL, NULL
965 },
966 { NULL, // QUANTUM FIREBALL ST3.2A
967 "^QUANTUM FIREBALL ST3.2A$",
968 ".*",
969 NULL, NULL, NULL, NULL
970 },
971 { NULL, // QUANTUM FIREBALL EX3.2A
972 "^QUANTUM FIREBALL EX3.2A$",
973 ".*",
974 NULL, NULL, NULL, NULL
975 },
976 { NULL, // QUANTUM FIREBALLP KX27.3
977 "^QUANTUM FIREBALLP KX27.3$",
978 ".*",
979 NULL, NULL, NULL, NULL
980 },
981 { NULL, // QUANTUM FIREBALLP KA10.1
982 "^QUANTUM FIREBALLP KA10.1$",
983 ".*",
984 NULL, NULL, NULL, NULL
985 },
986 /*------------------------------------------------------------
987 * End of table. Do not add entries below this marker.
988 *------------------------------------------------------------ */
989 {NULL, NULL, NULL, NULL, NULL, NULL, NULL}
990 };
991
992 // Searches knowndrives[] for a drive with the given model number and firmware
993 // string. If either the drive's model or firmware strings are not set by the
994 // manufacturer then values of NULL may be used. Returns the index of the
995 // first match in knowndrives[] or -1 if no match if found.
996 int lookupdrive(const char *model, const char *firmware)
997 {
998 regex_t regex;
999 int i, index;
1000 const char *empty = "";
1001
1002 model = model ? model : empty;
1003 firmware = firmware ? firmware : empty;
1004
1005 for (i = 0, index = -1; index == -1 && knowndrives[i].modelregexp; i++) {
1006 // Attempt to compile regular expression.
1007 if (compileregex(&regex, knowndrives[i].modelregexp, REG_EXTENDED))
1008 goto CONTINUE;
1009
1010 // Check whether model matches the regular expression in knowndrives[i].
1011 if (!regexec(&regex, model, 0, NULL, 0)) {
1012 // model matches, now check firmware.
1013 if (!knowndrives[i].firmwareregexp)
1014 // The firmware regular expression in knowndrives[i] is NULL, which is
1015 // considered a match.
1016 index = i;
1017 else {
1018 // Compare firmware against the regular expression in knowndrives[i].
1019 regfree(&regex); // Recycle regex.
1020 if (compileregex(&regex, knowndrives[i].firmwareregexp, REG_EXTENDED))
1021 goto CONTINUE;
1022 if (!regexec(&regex, firmware, 0, NULL, 0))
1023 index = i;
1024 }
1025 }
1026 CONTINUE:
1027 regfree(&regex);
1028 }
1029
1030 return index;
1031 }
1032
1033
1034 // Shows all presets for drives in knowndrives[].
1035 void showonepreset(const drivesettings *drivetable){
1036
1037 const unsigned char (* presets)[2] = drivetable->vendoropts;
1038 int first_preset = 1;
1039
1040 // Basic error check
1041 if (!drivetable || !drivetable->modelregexp){
1042 pout("Null known drive table pointer. Please report\n"
1043 "this error to smartmontools developers at " PACKAGE_BUGREPORT ".\n");
1044 return;
1045 }
1046
1047 // print model and firmware regular expressions
1048 pout("%-*s %s\n", TABLEPRINTWIDTH, "MODEL REGEXP:", drivetable->modelregexp);
1049 pout("%-*s %s\n", TABLEPRINTWIDTH, "FIRMWARE REGEXP:", drivetable->firmwareregexp ?
1050 drivetable->firmwareregexp : "");
1051 pout("%-*s %s\n", TABLEPRINTWIDTH, "MODEL FAMILY:", drivetable->modelfamily ?
1052 drivetable->modelfamily : "");
1053
1054 // if there are any presets, then show them
1055 if (presets && (*presets)[0]) while (1) {
1056 char out[256];
1057 const int attr = (*presets)[0], val = (*presets)[1];
1058 unsigned char fakearray[MAX_ATTRIBUTE_NUM];
1059
1060 // if we are at the end of the attribute list, break out
1061 if (!attr)
1062 break;
1063
1064 // This is a hack. ataPrintSmartAttribName() needs a pointer to an
1065 // "array" to dereference, so we provide such a pointer.
1066 fakearray[attr]=val;
1067 ataPrintSmartAttribName(out, attr, fakearray);
1068
1069 // Use leading zeros instead of spaces so that everything lines up.
1070 out[0] = (out[0] == ' ') ? '0' : out[0];
1071 out[1] = (out[1] == ' ') ? '0' : out[1];
1072 pout("%-*s %s\n", TABLEPRINTWIDTH, first_preset ? "ATTRIBUTE OPTIONS:" : "", out);
1073 first_preset = 0;
1074 presets++;
1075 }
1076 else
1077 pout("%-*s %s\n", TABLEPRINTWIDTH, "ATTRIBUTE OPTIONS:", "None preset; no -v options are required.");
1078
1079
1080 // Is a special purpose function defined? If so, describe it
1081 if (drivetable->specialpurpose){
1082 pout("%-*s ", TABLEPRINTWIDTH, "OTHER PRESETS:");
1083 pout("%s\n", drivetable->functiondesc ?
1084 drivetable->functiondesc : "A special purpose function "
1085 "is defined for this drive");
1086 }
1087
1088 // Print any special warnings
1089 if (drivetable->warningmsg){
1090 pout("%-*s ", TABLEPRINTWIDTH, "WARNINGS:");
1091 pout("%s\n", drivetable->warningmsg);
1092 }
1093
1094 return;
1095 }
1096
1097 // Shows all presets for drives in knowndrives[].
1098 // Returns <0 on syntax error in regular expressions.
1099 int showallpresets(void){
1100 int i;
1101 int rc = 0;
1102 regex_t regex;
1103
1104 // loop over all entries in the knowndrives[] table, printing them
1105 // out in a nice format
1106 for (i=0; knowndrives[i].modelregexp; i++){
1107 showonepreset(&knowndrives[i]);
1108 pout("\n");
1109 }
1110
1111 // Check all regular expressions
1112 for (i=0; knowndrives[i].modelregexp; i++){
1113 if (compileregex(&regex, knowndrives[i].modelregexp, REG_EXTENDED))
1114 rc = -1;
1115 if (knowndrives[i].firmwareregexp) {
1116 if (compileregex(&regex, knowndrives[i].firmwareregexp, REG_EXTENDED))
1117 rc = -1;
1118 }
1119 }
1120 pout("For information about adding a drive to the database see the FAQ on the\n");
1121 pout("smartmontools home page: " PACKAGE_HOMEPAGE "\n");
1122 return rc;
1123 }
1124
1125 // Shows all matching presets for a drive in knowndrives[].
1126 // Returns # matching entries.
1127 int showmatchingpresets(const char *model, const char *firmware){
1128 int i;
1129 int cnt = 0;
1130 const char * firmwaremsg = (firmware ? firmware : "(any)");
1131 regex_t regex;
1132
1133 for (i=0; knowndrives[i].modelregexp; i++){
1134 if (i > 0)
1135 regfree(&regex);
1136 if (compileregex(&regex, knowndrives[i].modelregexp, REG_EXTENDED))
1137 continue;
1138 if (regexec(&regex, model, 0, NULL, 0))
1139 continue;
1140 if (firmware && knowndrives[i].firmwareregexp) {
1141 regfree(&regex);
1142 if (compileregex(&regex, knowndrives[i].firmwareregexp, REG_EXTENDED))
1143 continue;
1144 if (regexec(&regex, firmware, 0, NULL, 0))
1145 continue;
1146 }
1147 if (++cnt == 1)
1148 pout("Drive found in smartmontools Database. Drive identity strings:\n"
1149 "%-*s %s\n"
1150 "%-*s %s\n"
1151 "match smartmontools Drive Database entry:\n",
1152 TABLEPRINTWIDTH, "MODEL:", model, TABLEPRINTWIDTH, "FIRMWARE:", firmwaremsg);
1153 else if (cnt == 2)
1154 pout("and match these additional entries:\n");
1155 showonepreset(&knowndrives[i]);
1156 pout("\n");
1157 }
1158 regfree(&regex);
1159 if (cnt == 0)
1160 pout("No presets are defined for this drive. Its identity strings:\n"
1161 "MODEL: %s\n"
1162 "FIRMWARE: %s\n"
1163 "do not match any of the known regular expressions.\n",
1164 model, firmwaremsg);
1165 return cnt;
1166 }
1167
1168 // Shows the presets (if any) that are available for the given drive.
1169 void showpresets(const struct ata_identify_device *drive){
1170 int i;
1171 char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1];
1172
1173 // get the drive's model/firmware strings
1174 formatdriveidstring(model, (char *)drive->model, MODEL_STRING_LENGTH);
1175 formatdriveidstring(firmware, (char *)drive->fw_rev, FIRMWARE_STRING_LENGTH);
1176
1177 // and search to see if they match values in the table
1178 if ((i = lookupdrive(model, firmware)) < 0) {
1179 // no matches found
1180 pout("No presets are defined for this drive. Its identity strings:\n"
1181 "MODEL: %s\n"
1182 "FIRMWARE: %s\n"
1183 "do not match any of the known regular expressions.\n"
1184 "Use -P showall to list all known regular expressions.\n",
1185 model, firmware);
1186 return;
1187 }
1188
1189 // We found a matching drive. Print out all information about it.
1190 pout("Drive found in smartmontools Database. Drive identity strings:\n"
1191 "%-*s %s\n"
1192 "%-*s %s\n"
1193 "match smartmontools Drive Database entry:\n",
1194 TABLEPRINTWIDTH, "MODEL:", model, TABLEPRINTWIDTH, "FIRMWARE:", firmware);
1195 showonepreset(&knowndrives[i]);
1196 return;
1197 }
1198
1199 // Sets preset vendor attribute options in opts by finding the entry
1200 // (if any) for the given drive in knowndrives[]. Values that have
1201 // already been set in opts will not be changed. Returns <0 if drive
1202 // not recognized else index >=0 into drive database.
1203 int applypresets(const struct ata_identify_device *drive, unsigned char **optsptr,
1204 smartmonctrl *con) {
1205 int i;
1206 unsigned char *opts;
1207 char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1];
1208
1209 if (*optsptr==NULL)
1210 bytes+=MAX_ATTRIBUTE_NUM;
1211
1212 if (*optsptr==NULL && !(*optsptr=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM,1))){
1213 pout("Unable to allocate memory in applypresets()");
1214 bytes-=MAX_ATTRIBUTE_NUM;
1215 EXIT(1);
1216 }
1217
1218 opts=*optsptr;
1219
1220 // get the drive's model/firmware strings
1221 formatdriveidstring(model, (char *)drive->model, MODEL_STRING_LENGTH);
1222 formatdriveidstring(firmware, (char *)drive->fw_rev, FIRMWARE_STRING_LENGTH);
1223
1224 // Look up the drive in knowndrives[].
1225 if ((i = lookupdrive(model, firmware)) >= 0) {
1226
1227 // if vendoropts is non-NULL then Attribute interpretation presets
1228 if (knowndrives[i].vendoropts) {
1229 const unsigned char (* presets)[2];
1230
1231 // For each attribute in list of attribute/val pairs...
1232 presets = knowndrives[i].vendoropts;
1233 while (1) {
1234 const int attr = (*presets)[0];
1235 const int val = (*presets)[1];
1236
1237 if (!attr)
1238 break;
1239
1240 // ... set attribute if user hasn't already done so.
1241 if (!opts[attr])
1242 opts[attr] = val;
1243 presets++;
1244 }
1245 }
1246
1247 // If a special-purpose function is defined for this drive then
1248 // call it. Note that if command line arguments or Directives
1249 // over-ride this choice, then the specialpurpose function that is
1250 // called must deal with this.
1251 if (knowndrives[i].specialpurpose)
1252 (*knowndrives[i].specialpurpose)(con);
1253 }
1254
1255 // return <0 if drive wasn't recognized, or index>=0 into database
1256 // if it was
1257 return i;
1258 }