aiclib.c 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411
  1. /*
  2. * Implementation of Utility functions for all SCSI device types.
  3. *
  4. * Copyright (c) 1997, 1998, 1999 Justin T. Gibbs.
  5. * Copyright (c) 1997, 1998 Kenneth D. Merry.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions, and the following disclaimer,
  13. * without modification, immediately at the beginning of the file.
  14. * 2. The name of the author may not be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  21. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. *
  29. * $FreeBSD: src/sys/cam/scsi/scsi_all.c,v 1.38 2002/09/23 04:56:35 mjacob Exp $
  30. * $Id$
  31. */
  32. #include <linux/blkdev.h>
  33. #include <linux/delay.h>
  34. #include <linux/version.h>
  35. /* Core SCSI definitions */
  36. #include <scsi/scsi_host.h>
  37. #include "aiclib.h"
  38. #include "cam.h"
  39. #ifndef FALSE
  40. #define FALSE 0
  41. #endif /* FALSE */
  42. #ifndef TRUE
  43. #define TRUE 1
  44. #endif /* TRUE */
  45. #ifndef ERESTART
  46. #define ERESTART -1 /* restart syscall */
  47. #endif
  48. #ifndef EJUSTRETURN
  49. #define EJUSTRETURN -2 /* don't modify regs, just return */
  50. #endif
  51. static int ascentrycomp(const void *key, const void *member);
  52. static int senseentrycomp(const void *key, const void *member);
  53. static void fetchtableentries(int sense_key, int asc, int ascq,
  54. struct scsi_inquiry_data *,
  55. const struct sense_key_table_entry **,
  56. const struct asc_table_entry **);
  57. static void * scsibsearch(const void *key, const void *base, size_t nmemb,
  58. size_t size,
  59. int (*compar)(const void *, const void *));
  60. typedef int (cam_quirkmatch_t)(caddr_t, caddr_t);
  61. static int cam_strmatch(const u_int8_t *str, const u_int8_t *pattern,
  62. int str_len);
  63. static caddr_t cam_quirkmatch(caddr_t target, caddr_t quirk_table,
  64. int num_entries, int entry_size,
  65. cam_quirkmatch_t *comp_func);
  66. #define SCSI_NO_SENSE_STRINGS 1
  67. #if !defined(SCSI_NO_SENSE_STRINGS)
  68. #define SST(asc, ascq, action, desc) \
  69. asc, ascq, action, desc
  70. #else
  71. static const char empty_string[] = "";
  72. #define SST(asc, ascq, action, desc) \
  73. asc, ascq, action, empty_string
  74. #endif
  75. static const struct sense_key_table_entry sense_key_table[] =
  76. {
  77. { SSD_KEY_NO_SENSE, SS_NOP, "NO SENSE" },
  78. { SSD_KEY_RECOVERED_ERROR, SS_NOP|SSQ_PRINT_SENSE, "RECOVERED ERROR" },
  79. {
  80. SSD_KEY_NOT_READY, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
  81. "NOT READY"
  82. },
  83. { SSD_KEY_MEDIUM_ERROR, SS_RDEF, "MEDIUM ERROR" },
  84. { SSD_KEY_HARDWARE_ERROR, SS_RDEF, "HARDWARE FAILURE" },
  85. { SSD_KEY_ILLEGAL_REQUEST, SS_FATAL|EINVAL, "ILLEGAL REQUEST" },
  86. { SSD_KEY_UNIT_ATTENTION, SS_FATAL|ENXIO, "UNIT ATTENTION" },
  87. { SSD_KEY_DATA_PROTECT, SS_FATAL|EACCES, "DATA PROTECT" },
  88. { SSD_KEY_BLANK_CHECK, SS_FATAL|ENOSPC, "BLANK CHECK" },
  89. { SSD_KEY_Vendor_Specific, SS_FATAL|EIO, "Vendor Specific" },
  90. { SSD_KEY_COPY_ABORTED, SS_FATAL|EIO, "COPY ABORTED" },
  91. { SSD_KEY_ABORTED_COMMAND, SS_RDEF, "ABORTED COMMAND" },
  92. { SSD_KEY_EQUAL, SS_NOP, "EQUAL" },
  93. { SSD_KEY_VOLUME_OVERFLOW, SS_FATAL|EIO, "VOLUME OVERFLOW" },
  94. { SSD_KEY_MISCOMPARE, SS_NOP, "MISCOMPARE" },
  95. { SSD_KEY_RESERVED, SS_FATAL|EIO, "RESERVED" }
  96. };
  97. static const int sense_key_table_size =
  98. sizeof(sense_key_table)/sizeof(sense_key_table[0]);
  99. static struct asc_table_entry quantum_fireball_entries[] = {
  100. {SST(0x04, 0x0b, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
  101. "Logical unit not ready, initializing cmd. required")}
  102. };
  103. static struct asc_table_entry sony_mo_entries[] = {
  104. {SST(0x04, 0x00, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
  105. "Logical unit not ready, cause not reportable")}
  106. };
  107. static struct scsi_sense_quirk_entry sense_quirk_table[] = {
  108. {
  109. /*
  110. * The Quantum Fireball ST and SE like to return 0x04 0x0b when
  111. * they really should return 0x04 0x02. 0x04,0x0b isn't
  112. * defined in any SCSI spec, and it isn't mentioned in the
  113. * hardware manual for these drives.
  114. */
  115. {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"},
  116. /*num_sense_keys*/0,
  117. sizeof(quantum_fireball_entries)/sizeof(struct asc_table_entry),
  118. /*sense key entries*/NULL,
  119. quantum_fireball_entries
  120. },
  121. {
  122. /*
  123. * This Sony MO drive likes to return 0x04, 0x00 when it
  124. * isn't spun up.
  125. */
  126. {T_DIRECT, SIP_MEDIA_REMOVABLE, "SONY", "SMO-*", "*"},
  127. /*num_sense_keys*/0,
  128. sizeof(sony_mo_entries)/sizeof(struct asc_table_entry),
  129. /*sense key entries*/NULL,
  130. sony_mo_entries
  131. }
  132. };
  133. static const int sense_quirk_table_size =
  134. sizeof(sense_quirk_table)/sizeof(sense_quirk_table[0]);
  135. static struct asc_table_entry asc_table[] = {
  136. /*
  137. * From File: ASC-NUM.TXT
  138. * SCSI ASC/ASCQ Assignments
  139. * Numeric Sorted Listing
  140. * as of 5/12/97
  141. *
  142. * D - DIRECT ACCESS DEVICE (SBC) device column key
  143. * .T - SEQUENTIAL ACCESS DEVICE (SSC) -------------------
  144. * . L - PRINTER DEVICE (SSC) blank = reserved
  145. * . P - PROCESSOR DEVICE (SPC) not blank = allowed
  146. * . .W - WRITE ONCE READ MULTIPLE DEVICE (SBC)
  147. * . . R - CD DEVICE (MMC)
  148. * . . S - SCANNER DEVICE (SGC)
  149. * . . .O - OPTICAL MEMORY DEVICE (SBC)
  150. * . . . M - MEDIA CHANGER DEVICE (SMC)
  151. * . . . C - COMMUNICATION DEVICE (SSC)
  152. * . . . .A - STORAGE ARRAY DEVICE (SCC)
  153. * . . . . E - ENCLOSURE SERVICES DEVICE (SES)
  154. * DTLPWRSOMCAE ASC ASCQ Action Description
  155. * ------------ ---- ---- ------ -----------------------------------*/
  156. /* DTLPWRSOMCAE */{SST(0x00, 0x00, SS_NOP,
  157. "No additional sense information") },
  158. /* T S */{SST(0x00, 0x01, SS_RDEF,
  159. "Filemark detected") },
  160. /* T S */{SST(0x00, 0x02, SS_RDEF,
  161. "End-of-partition/medium detected") },
  162. /* T */{SST(0x00, 0x03, SS_RDEF,
  163. "Setmark detected") },
  164. /* T S */{SST(0x00, 0x04, SS_RDEF,
  165. "Beginning-of-partition/medium detected") },
  166. /* T S */{SST(0x00, 0x05, SS_RDEF,
  167. "End-of-data detected") },
  168. /* DTLPWRSOMCAE */{SST(0x00, 0x06, SS_RDEF,
  169. "I/O process terminated") },
  170. /* R */{SST(0x00, 0x11, SS_FATAL|EBUSY,
  171. "Audio play operation in progress") },
  172. /* R */{SST(0x00, 0x12, SS_NOP,
  173. "Audio play operation paused") },
  174. /* R */{SST(0x00, 0x13, SS_NOP,
  175. "Audio play operation successfully completed") },
  176. /* R */{SST(0x00, 0x14, SS_RDEF,
  177. "Audio play operation stopped due to error") },
  178. /* R */{SST(0x00, 0x15, SS_NOP,
  179. "No current audio status to return") },
  180. /* DTLPWRSOMCAE */{SST(0x00, 0x16, SS_FATAL|EBUSY,
  181. "Operation in progress") },
  182. /* DTL WRSOM AE */{SST(0x00, 0x17, SS_RDEF,
  183. "Cleaning requested") },
  184. /* D W O */{SST(0x01, 0x00, SS_RDEF,
  185. "No index/sector signal") },
  186. /* D WR OM */{SST(0x02, 0x00, SS_RDEF,
  187. "No seek complete") },
  188. /* DTL W SO */{SST(0x03, 0x00, SS_RDEF,
  189. "Peripheral device write fault") },
  190. /* T */{SST(0x03, 0x01, SS_RDEF,
  191. "No write current") },
  192. /* T */{SST(0x03, 0x02, SS_RDEF,
  193. "Excessive write errors") },
  194. /* DTLPWRSOMCAE */{SST(0x04, 0x00,
  195. SS_TUR|SSQ_DELAY|SSQ_MANY|SSQ_DECREMENT_COUNT|EIO,
  196. "Logical unit not ready, cause not reportable") },
  197. /* DTLPWRSOMCAE */{SST(0x04, 0x01,
  198. SS_TUR|SSQ_DELAY|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
  199. "Logical unit is in process of becoming ready") },
  200. /* DTLPWRSOMCAE */{SST(0x04, 0x02, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
  201. "Logical unit not ready, initializing cmd. required") },
  202. /* DTLPWRSOMCAE */{SST(0x04, 0x03, SS_FATAL|ENXIO,
  203. "Logical unit not ready, manual intervention required")},
  204. /* DTL O */{SST(0x04, 0x04, SS_FATAL|EBUSY,
  205. "Logical unit not ready, format in progress") },
  206. /* DT W OMCA */{SST(0x04, 0x05, SS_FATAL|EBUSY,
  207. "Logical unit not ready, rebuild in progress") },
  208. /* DT W OMCA */{SST(0x04, 0x06, SS_FATAL|EBUSY,
  209. "Logical unit not ready, recalculation in progress") },
  210. /* DTLPWRSOMCAE */{SST(0x04, 0x07, SS_FATAL|EBUSY,
  211. "Logical unit not ready, operation in progress") },
  212. /* R */{SST(0x04, 0x08, SS_FATAL|EBUSY,
  213. "Logical unit not ready, long write in progress") },
  214. /* DTL WRSOMCAE */{SST(0x05, 0x00, SS_RDEF,
  215. "Logical unit does not respond to selection") },
  216. /* D WR OM */{SST(0x06, 0x00, SS_RDEF,
  217. "No reference position found") },
  218. /* DTL WRSOM */{SST(0x07, 0x00, SS_RDEF,
  219. "Multiple peripheral devices selected") },
  220. /* DTL WRSOMCAE */{SST(0x08, 0x00, SS_RDEF,
  221. "Logical unit communication failure") },
  222. /* DTL WRSOMCAE */{SST(0x08, 0x01, SS_RDEF,
  223. "Logical unit communication time-out") },
  224. /* DTL WRSOMCAE */{SST(0x08, 0x02, SS_RDEF,
  225. "Logical unit communication parity error") },
  226. /* DT R OM */{SST(0x08, 0x03, SS_RDEF,
  227. "Logical unit communication crc error (ultra-dma/32)")},
  228. /* DT WR O */{SST(0x09, 0x00, SS_RDEF,
  229. "Track following error") },
  230. /* WR O */{SST(0x09, 0x01, SS_RDEF,
  231. "Tracking servo failure") },
  232. /* WR O */{SST(0x09, 0x02, SS_RDEF,
  233. "Focus servo failure") },
  234. /* WR O */{SST(0x09, 0x03, SS_RDEF,
  235. "Spindle servo failure") },
  236. /* DT WR O */{SST(0x09, 0x04, SS_RDEF,
  237. "Head select fault") },
  238. /* DTLPWRSOMCAE */{SST(0x0A, 0x00, SS_FATAL|ENOSPC,
  239. "Error log overflow") },
  240. /* DTLPWRSOMCAE */{SST(0x0B, 0x00, SS_RDEF,
  241. "Warning") },
  242. /* DTLPWRSOMCAE */{SST(0x0B, 0x01, SS_RDEF,
  243. "Specified temperature exceeded") },
  244. /* DTLPWRSOMCAE */{SST(0x0B, 0x02, SS_RDEF,
  245. "Enclosure degraded") },
  246. /* T RS */{SST(0x0C, 0x00, SS_RDEF,
  247. "Write error") },
  248. /* D W O */{SST(0x0C, 0x01, SS_NOP|SSQ_PRINT_SENSE,
  249. "Write error - recovered with auto reallocation") },
  250. /* D W O */{SST(0x0C, 0x02, SS_RDEF,
  251. "Write error - auto reallocation failed") },
  252. /* D W O */{SST(0x0C, 0x03, SS_RDEF,
  253. "Write error - recommend reassignment") },
  254. /* DT W O */{SST(0x0C, 0x04, SS_RDEF,
  255. "Compression check miscompare error") },
  256. /* DT W O */{SST(0x0C, 0x05, SS_RDEF,
  257. "Data expansion occurred during compression") },
  258. /* DT W O */{SST(0x0C, 0x06, SS_RDEF,
  259. "Block not compressible") },
  260. /* R */{SST(0x0C, 0x07, SS_RDEF,
  261. "Write error - recovery needed") },
  262. /* R */{SST(0x0C, 0x08, SS_RDEF,
  263. "Write error - recovery failed") },
  264. /* R */{SST(0x0C, 0x09, SS_RDEF,
  265. "Write error - loss of streaming") },
  266. /* R */{SST(0x0C, 0x0A, SS_RDEF,
  267. "Write error - padding blocks added") },
  268. /* D W O */{SST(0x10, 0x00, SS_RDEF,
  269. "ID CRC or ECC error") },
  270. /* DT WRSO */{SST(0x11, 0x00, SS_RDEF,
  271. "Unrecovered read error") },
  272. /* DT W SO */{SST(0x11, 0x01, SS_RDEF,
  273. "Read retries exhausted") },
  274. /* DT W SO */{SST(0x11, 0x02, SS_RDEF,
  275. "Error too long to correct") },
  276. /* DT W SO */{SST(0x11, 0x03, SS_RDEF,
  277. "Multiple read errors") },
  278. /* D W O */{SST(0x11, 0x04, SS_RDEF,
  279. "Unrecovered read error - auto reallocate failed") },
  280. /* WR O */{SST(0x11, 0x05, SS_RDEF,
  281. "L-EC uncorrectable error") },
  282. /* WR O */{SST(0x11, 0x06, SS_RDEF,
  283. "CIRC unrecovered error") },
  284. /* W O */{SST(0x11, 0x07, SS_RDEF,
  285. "Data re-synchronization error") },
  286. /* T */{SST(0x11, 0x08, SS_RDEF,
  287. "Incomplete block read") },
  288. /* T */{SST(0x11, 0x09, SS_RDEF,
  289. "No gap found") },
  290. /* DT O */{SST(0x11, 0x0A, SS_RDEF,
  291. "Miscorrected error") },
  292. /* D W O */{SST(0x11, 0x0B, SS_RDEF,
  293. "Unrecovered read error - recommend reassignment") },
  294. /* D W O */{SST(0x11, 0x0C, SS_RDEF,
  295. "Unrecovered read error - recommend rewrite the data")},
  296. /* DT WR O */{SST(0x11, 0x0D, SS_RDEF,
  297. "De-compression CRC error") },
  298. /* DT WR O */{SST(0x11, 0x0E, SS_RDEF,
  299. "Cannot decompress using declared algorithm") },
  300. /* R */{SST(0x11, 0x0F, SS_RDEF,
  301. "Error reading UPC/EAN number") },
  302. /* R */{SST(0x11, 0x10, SS_RDEF,
  303. "Error reading ISRC number") },
  304. /* R */{SST(0x11, 0x11, SS_RDEF,
  305. "Read error - loss of streaming") },
  306. /* D W O */{SST(0x12, 0x00, SS_RDEF,
  307. "Address mark not found for id field") },
  308. /* D W O */{SST(0x13, 0x00, SS_RDEF,
  309. "Address mark not found for data field") },
  310. /* DTL WRSO */{SST(0x14, 0x00, SS_RDEF,
  311. "Recorded entity not found") },
  312. /* DT WR O */{SST(0x14, 0x01, SS_RDEF,
  313. "Record not found") },
  314. /* T */{SST(0x14, 0x02, SS_RDEF,
  315. "Filemark or setmark not found") },
  316. /* T */{SST(0x14, 0x03, SS_RDEF,
  317. "End-of-data not found") },
  318. /* T */{SST(0x14, 0x04, SS_RDEF,
  319. "Block sequence error") },
  320. /* DT W O */{SST(0x14, 0x05, SS_RDEF,
  321. "Record not found - recommend reassignment") },
  322. /* DT W O */{SST(0x14, 0x06, SS_RDEF,
  323. "Record not found - data auto-reallocated") },
  324. /* DTL WRSOM */{SST(0x15, 0x00, SS_RDEF,
  325. "Random positioning error") },
  326. /* DTL WRSOM */{SST(0x15, 0x01, SS_RDEF,
  327. "Mechanical positioning error") },
  328. /* DT WR O */{SST(0x15, 0x02, SS_RDEF,
  329. "Positioning error detected by read of medium") },
  330. /* D W O */{SST(0x16, 0x00, SS_RDEF,
  331. "Data synchronization mark error") },
  332. /* D W O */{SST(0x16, 0x01, SS_RDEF,
  333. "Data sync error - data rewritten") },
  334. /* D W O */{SST(0x16, 0x02, SS_RDEF,
  335. "Data sync error - recommend rewrite") },
  336. /* D W O */{SST(0x16, 0x03, SS_NOP|SSQ_PRINT_SENSE,
  337. "Data sync error - data auto-reallocated") },
  338. /* D W O */{SST(0x16, 0x04, SS_RDEF,
  339. "Data sync error - recommend reassignment") },
  340. /* DT WRSO */{SST(0x17, 0x00, SS_NOP|SSQ_PRINT_SENSE,
  341. "Recovered data with no error correction applied") },
  342. /* DT WRSO */{SST(0x17, 0x01, SS_NOP|SSQ_PRINT_SENSE,
  343. "Recovered data with retries") },
  344. /* DT WR O */{SST(0x17, 0x02, SS_NOP|SSQ_PRINT_SENSE,
  345. "Recovered data with positive head offset") },
  346. /* DT WR O */{SST(0x17, 0x03, SS_NOP|SSQ_PRINT_SENSE,
  347. "Recovered data with negative head offset") },
  348. /* WR O */{SST(0x17, 0x04, SS_NOP|SSQ_PRINT_SENSE,
  349. "Recovered data with retries and/or CIRC applied") },
  350. /* D WR O */{SST(0x17, 0x05, SS_NOP|SSQ_PRINT_SENSE,
  351. "Recovered data using previous sector id") },
  352. /* D W O */{SST(0x17, 0x06, SS_NOP|SSQ_PRINT_SENSE,
  353. "Recovered data without ECC - data auto-reallocated") },
  354. /* D W O */{SST(0x17, 0x07, SS_NOP|SSQ_PRINT_SENSE,
  355. "Recovered data without ECC - recommend reassignment")},
  356. /* D W O */{SST(0x17, 0x08, SS_NOP|SSQ_PRINT_SENSE,
  357. "Recovered data without ECC - recommend rewrite") },
  358. /* D W O */{SST(0x17, 0x09, SS_NOP|SSQ_PRINT_SENSE,
  359. "Recovered data without ECC - data rewritten") },
  360. /* D W O */{SST(0x18, 0x00, SS_NOP|SSQ_PRINT_SENSE,
  361. "Recovered data with error correction applied") },
  362. /* D WR O */{SST(0x18, 0x01, SS_NOP|SSQ_PRINT_SENSE,
  363. "Recovered data with error corr. & retries applied") },
  364. /* D WR O */{SST(0x18, 0x02, SS_NOP|SSQ_PRINT_SENSE,
  365. "Recovered data - data auto-reallocated") },
  366. /* R */{SST(0x18, 0x03, SS_NOP|SSQ_PRINT_SENSE,
  367. "Recovered data with CIRC") },
  368. /* R */{SST(0x18, 0x04, SS_NOP|SSQ_PRINT_SENSE,
  369. "Recovered data with L-EC") },
  370. /* D WR O */{SST(0x18, 0x05, SS_NOP|SSQ_PRINT_SENSE,
  371. "Recovered data - recommend reassignment") },
  372. /* D WR O */{SST(0x18, 0x06, SS_NOP|SSQ_PRINT_SENSE,
  373. "Recovered data - recommend rewrite") },
  374. /* D W O */{SST(0x18, 0x07, SS_NOP|SSQ_PRINT_SENSE,
  375. "Recovered data with ECC - data rewritten") },
  376. /* D O */{SST(0x19, 0x00, SS_RDEF,
  377. "Defect list error") },
  378. /* D O */{SST(0x19, 0x01, SS_RDEF,
  379. "Defect list not available") },
  380. /* D O */{SST(0x19, 0x02, SS_RDEF,
  381. "Defect list error in primary list") },
  382. /* D O */{SST(0x19, 0x03, SS_RDEF,
  383. "Defect list error in grown list") },
  384. /* DTLPWRSOMCAE */{SST(0x1A, 0x00, SS_RDEF,
  385. "Parameter list length error") },
  386. /* DTLPWRSOMCAE */{SST(0x1B, 0x00, SS_RDEF,
  387. "Synchronous data transfer error") },
  388. /* D O */{SST(0x1C, 0x00, SS_RDEF,
  389. "Defect list not found") },
  390. /* D O */{SST(0x1C, 0x01, SS_RDEF,
  391. "Primary defect list not found") },
  392. /* D O */{SST(0x1C, 0x02, SS_RDEF,
  393. "Grown defect list not found") },
  394. /* D W O */{SST(0x1D, 0x00, SS_FATAL,
  395. "Miscompare during verify operation" )},
  396. /* D W O */{SST(0x1E, 0x00, SS_NOP|SSQ_PRINT_SENSE,
  397. "Recovered id with ecc correction") },
  398. /* D O */{SST(0x1F, 0x00, SS_RDEF,
  399. "Partial defect list transfer") },
  400. /* DTLPWRSOMCAE */{SST(0x20, 0x00, SS_FATAL|EINVAL,
  401. "Invalid command operation code") },
  402. /* DT WR OM */{SST(0x21, 0x00, SS_FATAL|EINVAL,
  403. "Logical block address out of range" )},
  404. /* DT WR OM */{SST(0x21, 0x01, SS_FATAL|EINVAL,
  405. "Invalid element address") },
  406. /* D */{SST(0x22, 0x00, SS_FATAL|EINVAL,
  407. "Illegal function") }, /* Deprecated. Use 20 00, 24 00, or 26 00 instead */
  408. /* DTLPWRSOMCAE */{SST(0x24, 0x00, SS_FATAL|EINVAL,
  409. "Invalid field in CDB") },
  410. /* DTLPWRSOMCAE */{SST(0x25, 0x00, SS_FATAL|ENXIO,
  411. "Logical unit not supported") },
  412. /* DTLPWRSOMCAE */{SST(0x26, 0x00, SS_FATAL|EINVAL,
  413. "Invalid field in parameter list") },
  414. /* DTLPWRSOMCAE */{SST(0x26, 0x01, SS_FATAL|EINVAL,
  415. "Parameter not supported") },
  416. /* DTLPWRSOMCAE */{SST(0x26, 0x02, SS_FATAL|EINVAL,
  417. "Parameter value invalid") },
  418. /* DTLPWRSOMCAE */{SST(0x26, 0x03, SS_FATAL|EINVAL,
  419. "Threshold parameters not supported") },
  420. /* DTLPWRSOMCAE */{SST(0x26, 0x04, SS_FATAL|EINVAL,
  421. "Invalid release of active persistent reservation") },
  422. /* DT W O */{SST(0x27, 0x00, SS_FATAL|EACCES,
  423. "Write protected") },
  424. /* DT W O */{SST(0x27, 0x01, SS_FATAL|EACCES,
  425. "Hardware write protected") },
  426. /* DT W O */{SST(0x27, 0x02, SS_FATAL|EACCES,
  427. "Logical unit software write protected") },
  428. /* T */{SST(0x27, 0x03, SS_FATAL|EACCES,
  429. "Associated write protect") },
  430. /* T */{SST(0x27, 0x04, SS_FATAL|EACCES,
  431. "Persistent write protect") },
  432. /* T */{SST(0x27, 0x05, SS_FATAL|EACCES,
  433. "Permanent write protect") },
  434. /* DTLPWRSOMCAE */{SST(0x28, 0x00, SS_RDEF,
  435. "Not ready to ready change, medium may have changed") },
  436. /* DTLPWRSOMCAE */{SST(0x28, 0x01, SS_FATAL|ENXIO,
  437. "Import or export element accessed") },
  438. /*
  439. * XXX JGibbs - All of these should use the same errno, but I don't think
  440. * ENXIO is the correct choice. Should we borrow from the networking
  441. * errnos? ECONNRESET anyone?
  442. */
  443. /* DTLPWRSOMCAE */{SST(0x29, 0x00, SS_RDEF,
  444. "Power on, reset, or bus device reset occurred") },
  445. /* DTLPWRSOMCAE */{SST(0x29, 0x01, SS_RDEF,
  446. "Power on occurred") },
  447. /* DTLPWRSOMCAE */{SST(0x29, 0x02, SS_RDEF,
  448. "Scsi bus reset occurred") },
  449. /* DTLPWRSOMCAE */{SST(0x29, 0x03, SS_RDEF,
  450. "Bus device reset function occurred") },
  451. /* DTLPWRSOMCAE */{SST(0x29, 0x04, SS_RDEF,
  452. "Device internal reset") },
  453. /* DTLPWRSOMCAE */{SST(0x29, 0x05, SS_RDEF,
  454. "Transceiver mode changed to single-ended") },
  455. /* DTLPWRSOMCAE */{SST(0x29, 0x06, SS_RDEF,
  456. "Transceiver mode changed to LVD") },
  457. /* DTL WRSOMCAE */{SST(0x2A, 0x00, SS_RDEF,
  458. "Parameters changed") },
  459. /* DTL WRSOMCAE */{SST(0x2A, 0x01, SS_RDEF,
  460. "Mode parameters changed") },
  461. /* DTL WRSOMCAE */{SST(0x2A, 0x02, SS_RDEF,
  462. "Log parameters changed") },
  463. /* DTLPWRSOMCAE */{SST(0x2A, 0x03, SS_RDEF,
  464. "Reservations preempted") },
  465. /* DTLPWRSO C */{SST(0x2B, 0x00, SS_RDEF,
  466. "Copy cannot execute since host cannot disconnect") },
  467. /* DTLPWRSOMCAE */{SST(0x2C, 0x00, SS_RDEF,
  468. "Command sequence error") },
  469. /* S */{SST(0x2C, 0x01, SS_RDEF,
  470. "Too many windows specified") },
  471. /* S */{SST(0x2C, 0x02, SS_RDEF,
  472. "Invalid combination of windows specified") },
  473. /* R */{SST(0x2C, 0x03, SS_RDEF,
  474. "Current program area is not empty") },
  475. /* R */{SST(0x2C, 0x04, SS_RDEF,
  476. "Current program area is empty") },
  477. /* T */{SST(0x2D, 0x00, SS_RDEF,
  478. "Overwrite error on update in place") },
  479. /* DTLPWRSOMCAE */{SST(0x2F, 0x00, SS_RDEF,
  480. "Commands cleared by another initiator") },
  481. /* DT WR OM */{SST(0x30, 0x00, SS_RDEF,
  482. "Incompatible medium installed") },
  483. /* DT WR O */{SST(0x30, 0x01, SS_RDEF,
  484. "Cannot read medium - unknown format") },
  485. /* DT WR O */{SST(0x30, 0x02, SS_RDEF,
  486. "Cannot read medium - incompatible format") },
  487. /* DT */{SST(0x30, 0x03, SS_RDEF,
  488. "Cleaning cartridge installed") },
  489. /* DT WR O */{SST(0x30, 0x04, SS_RDEF,
  490. "Cannot write medium - unknown format") },
  491. /* DT WR O */{SST(0x30, 0x05, SS_RDEF,
  492. "Cannot write medium - incompatible format") },
  493. /* DT W O */{SST(0x30, 0x06, SS_RDEF,
  494. "Cannot format medium - incompatible medium") },
  495. /* DTL WRSOM AE */{SST(0x30, 0x07, SS_RDEF,
  496. "Cleaning failure") },
  497. /* R */{SST(0x30, 0x08, SS_RDEF,
  498. "Cannot write - application code mismatch") },
  499. /* R */{SST(0x30, 0x09, SS_RDEF,
  500. "Current session not fixated for append") },
  501. /* DT WR O */{SST(0x31, 0x00, SS_RDEF,
  502. "Medium format corrupted") },
  503. /* D L R O */{SST(0x31, 0x01, SS_RDEF,
  504. "Format command failed") },
  505. /* D W O */{SST(0x32, 0x00, SS_RDEF,
  506. "No defect spare location available") },
  507. /* D W O */{SST(0x32, 0x01, SS_RDEF,
  508. "Defect list update failure") },
  509. /* T */{SST(0x33, 0x00, SS_RDEF,
  510. "Tape length error") },
  511. /* DTLPWRSOMCAE */{SST(0x34, 0x00, SS_RDEF,
  512. "Enclosure failure") },
  513. /* DTLPWRSOMCAE */{SST(0x35, 0x00, SS_RDEF,
  514. "Enclosure services failure") },
  515. /* DTLPWRSOMCAE */{SST(0x35, 0x01, SS_RDEF,
  516. "Unsupported enclosure function") },
  517. /* DTLPWRSOMCAE */{SST(0x35, 0x02, SS_RDEF,
  518. "Enclosure services unavailable") },
  519. /* DTLPWRSOMCAE */{SST(0x35, 0x03, SS_RDEF,
  520. "Enclosure services transfer failure") },
  521. /* DTLPWRSOMCAE */{SST(0x35, 0x04, SS_RDEF,
  522. "Enclosure services transfer refused") },
  523. /* L */{SST(0x36, 0x00, SS_RDEF,
  524. "Ribbon, ink, or toner failure") },
  525. /* DTL WRSOMCAE */{SST(0x37, 0x00, SS_RDEF,
  526. "Rounded parameter") },
  527. /* DTL WRSOMCAE */{SST(0x39, 0x00, SS_RDEF,
  528. "Saving parameters not supported") },
  529. /* DTL WRSOM */{SST(0x3A, 0x00, SS_NOP,
  530. "Medium not present") },
  531. /* DT WR OM */{SST(0x3A, 0x01, SS_NOP,
  532. "Medium not present - tray closed") },
  533. /* DT WR OM */{SST(0x3A, 0x01, SS_NOP,
  534. "Medium not present - tray open") },
  535. /* DT WR OM */{SST(0x3A, 0x03, SS_NOP,
  536. "Medium not present - Loadable") },
  537. /* DT WR OM */{SST(0x3A, 0x04, SS_NOP,
  538. "Medium not present - medium auxiliary "
  539. "memory accessible") },
  540. /* DT WR OM */{SST(0x3A, 0xFF, SS_NOP, NULL) },/* Range 0x05->0xFF */
  541. /* TL */{SST(0x3B, 0x00, SS_RDEF,
  542. "Sequential positioning error") },
  543. /* T */{SST(0x3B, 0x01, SS_RDEF,
  544. "Tape position error at beginning-of-medium") },
  545. /* T */{SST(0x3B, 0x02, SS_RDEF,
  546. "Tape position error at end-of-medium") },
  547. /* L */{SST(0x3B, 0x03, SS_RDEF,
  548. "Tape or electronic vertical forms unit not ready") },
  549. /* L */{SST(0x3B, 0x04, SS_RDEF,
  550. "Slew failure") },
  551. /* L */{SST(0x3B, 0x05, SS_RDEF,
  552. "Paper jam") },
  553. /* L */{SST(0x3B, 0x06, SS_RDEF,
  554. "Failed to sense top-of-form") },
  555. /* L */{SST(0x3B, 0x07, SS_RDEF,
  556. "Failed to sense bottom-of-form") },
  557. /* T */{SST(0x3B, 0x08, SS_RDEF,
  558. "Reposition error") },
  559. /* S */{SST(0x3B, 0x09, SS_RDEF,
  560. "Read past end of medium") },
  561. /* S */{SST(0x3B, 0x0A, SS_RDEF,
  562. "Read past beginning of medium") },
  563. /* S */{SST(0x3B, 0x0B, SS_RDEF,
  564. "Position past end of medium") },
  565. /* T S */{SST(0x3B, 0x0C, SS_RDEF,
  566. "Position past beginning of medium") },
  567. /* DT WR OM */{SST(0x3B, 0x0D, SS_FATAL|ENOSPC,
  568. "Medium destination element full") },
  569. /* DT WR OM */{SST(0x3B, 0x0E, SS_RDEF,
  570. "Medium source element empty") },
  571. /* R */{SST(0x3B, 0x0F, SS_RDEF,
  572. "End of medium reached") },
  573. /* DT WR OM */{SST(0x3B, 0x11, SS_RDEF,
  574. "Medium magazine not accessible") },
  575. /* DT WR OM */{SST(0x3B, 0x12, SS_RDEF,
  576. "Medium magazine removed") },
  577. /* DT WR OM */{SST(0x3B, 0x13, SS_RDEF,
  578. "Medium magazine inserted") },
  579. /* DT WR OM */{SST(0x3B, 0x14, SS_RDEF,
  580. "Medium magazine locked") },
  581. /* DT WR OM */{SST(0x3B, 0x15, SS_RDEF,
  582. "Medium magazine unlocked") },
  583. /* DTLPWRSOMCAE */{SST(0x3D, 0x00, SS_RDEF,
  584. "Invalid bits in identify message") },
  585. /* DTLPWRSOMCAE */{SST(0x3E, 0x00, SS_RDEF,
  586. "Logical unit has not self-configured yet") },
  587. /* DTLPWRSOMCAE */{SST(0x3E, 0x01, SS_RDEF,
  588. "Logical unit failure") },
  589. /* DTLPWRSOMCAE */{SST(0x3E, 0x02, SS_RDEF,
  590. "Timeout on logical unit") },
  591. /* DTLPWRSOMCAE */{SST(0x3F, 0x00, SS_RDEF,
  592. "Target operating conditions have changed") },
  593. /* DTLPWRSOMCAE */{SST(0x3F, 0x01, SS_RDEF,
  594. "Microcode has been changed") },
  595. /* DTLPWRSOMC */{SST(0x3F, 0x02, SS_RDEF,
  596. "Changed operating definition") },
  597. /* DTLPWRSOMCAE */{SST(0x3F, 0x03, SS_INQ_REFRESH|SSQ_DECREMENT_COUNT,
  598. "Inquiry data has changed") },
  599. /* DT WR OMCAE */{SST(0x3F, 0x04, SS_RDEF,
  600. "Component device attached") },
  601. /* DT WR OMCAE */{SST(0x3F, 0x05, SS_RDEF,
  602. "Device identifier changed") },
  603. /* DT WR OMCAE */{SST(0x3F, 0x06, SS_RDEF,
  604. "Redundancy group created or modified") },
  605. /* DT WR OMCAE */{SST(0x3F, 0x07, SS_RDEF,
  606. "Redundancy group deleted") },
  607. /* DT WR OMCAE */{SST(0x3F, 0x08, SS_RDEF,
  608. "Spare created or modified") },
  609. /* DT WR OMCAE */{SST(0x3F, 0x09, SS_RDEF,
  610. "Spare deleted") },
  611. /* DT WR OMCAE */{SST(0x3F, 0x0A, SS_RDEF,
  612. "Volume set created or modified") },
  613. /* DT WR OMCAE */{SST(0x3F, 0x0B, SS_RDEF,
  614. "Volume set deleted") },
  615. /* DT WR OMCAE */{SST(0x3F, 0x0C, SS_RDEF,
  616. "Volume set deassigned") },
  617. /* DT WR OMCAE */{SST(0x3F, 0x0D, SS_RDEF,
  618. "Volume set reassigned") },
  619. /* DTLPWRSOMCAE */{SST(0x3F, 0x0E, SS_RDEF,
  620. "Reported luns data has changed") },
  621. /* DTLPWRSOMCAE */{SST(0x3F, 0x0F, SS_RETRY|SSQ_DECREMENT_COUNT
  622. | SSQ_DELAY_RANDOM|EBUSY,
  623. "Echo buffer overwritten") },
  624. /* DT WR OM B*/{SST(0x3F, 0x0F, SS_RDEF, "Medium Loadable") },
  625. /* DT WR OM B*/{SST(0x3F, 0x0F, SS_RDEF,
  626. "Medium auxiliary memory accessible") },
  627. /* D */{SST(0x40, 0x00, SS_RDEF,
  628. "Ram failure") }, /* deprecated - use 40 NN instead */
  629. /* DTLPWRSOMCAE */{SST(0x40, 0x80, SS_RDEF,
  630. "Diagnostic failure: ASCQ = Component ID") },
  631. /* DTLPWRSOMCAE */{SST(0x40, 0xFF, SS_RDEF|SSQ_RANGE,
  632. NULL) },/* Range 0x80->0xFF */
  633. /* D */{SST(0x41, 0x00, SS_RDEF,
  634. "Data path failure") }, /* deprecated - use 40 NN instead */
  635. /* D */{SST(0x42, 0x00, SS_RDEF,
  636. "Power-on or self-test failure") }, /* deprecated - use 40 NN instead */
  637. /* DTLPWRSOMCAE */{SST(0x43, 0x00, SS_RDEF,
  638. "Message error") },
  639. /* DTLPWRSOMCAE */{SST(0x44, 0x00, SS_RDEF,
  640. "Internal target failure") },
  641. /* DTLPWRSOMCAE */{SST(0x45, 0x00, SS_RDEF,
  642. "Select or reselect failure") },
  643. /* DTLPWRSOMC */{SST(0x46, 0x00, SS_RDEF,
  644. "Unsuccessful soft reset") },
  645. /* DTLPWRSOMCAE */{SST(0x47, 0x00, SS_RDEF|SSQ_FALLBACK,
  646. "SCSI parity error") },
  647. /* DTLPWRSOMCAE */{SST(0x47, 0x01, SS_RDEF|SSQ_FALLBACK,
  648. "Data Phase CRC error detected") },
  649. /* DTLPWRSOMCAE */{SST(0x47, 0x02, SS_RDEF|SSQ_FALLBACK,
  650. "SCSI parity error detected during ST data phase") },
  651. /* DTLPWRSOMCAE */{SST(0x47, 0x03, SS_RDEF|SSQ_FALLBACK,
  652. "Information Unit iuCRC error") },
  653. /* DTLPWRSOMCAE */{SST(0x47, 0x04, SS_RDEF|SSQ_FALLBACK,
  654. "Asynchronous information protection error detected") },
  655. /* DTLPWRSOMCAE */{SST(0x47, 0x05, SS_RDEF|SSQ_FALLBACK,
  656. "Protocol server CRC error") },
  657. /* DTLPWRSOMCAE */{SST(0x48, 0x00, SS_RDEF|SSQ_FALLBACK,
  658. "Initiator detected error message received") },
  659. /* DTLPWRSOMCAE */{SST(0x49, 0x00, SS_RDEF,
  660. "Invalid message error") },
  661. /* DTLPWRSOMCAE */{SST(0x4A, 0x00, SS_RDEF,
  662. "Command phase error") },
  663. /* DTLPWRSOMCAE */{SST(0x4B, 0x00, SS_RDEF,
  664. "Data phase error") },
  665. /* DTLPWRSOMCAE */{SST(0x4C, 0x00, SS_RDEF,
  666. "Logical unit failed self-configuration") },
  667. /* DTLPWRSOMCAE */{SST(0x4D, 0x00, SS_RDEF,
  668. "Tagged overlapped commands: ASCQ = Queue tag ID") },
  669. /* DTLPWRSOMCAE */{SST(0x4D, 0xFF, SS_RDEF|SSQ_RANGE,
  670. NULL)}, /* Range 0x00->0xFF */
  671. /* DTLPWRSOMCAE */{SST(0x4E, 0x00, SS_RDEF,
  672. "Overlapped commands attempted") },
  673. /* T */{SST(0x50, 0x00, SS_RDEF,
  674. "Write append error") },
  675. /* T */{SST(0x50, 0x01, SS_RDEF,
  676. "Write append position error") },
  677. /* T */{SST(0x50, 0x02, SS_RDEF,
  678. "Position error related to timing") },
  679. /* T O */{SST(0x51, 0x00, SS_RDEF,
  680. "Erase failure") },
  681. /* T */{SST(0x52, 0x00, SS_RDEF,
  682. "Cartridge fault") },
  683. /* DTL WRSOM */{SST(0x53, 0x00, SS_RDEF,
  684. "Media load or eject failed") },
  685. /* T */{SST(0x53, 0x01, SS_RDEF,
  686. "Unload tape failure") },
  687. /* DT WR OM */{SST(0x53, 0x02, SS_RDEF,
  688. "Medium removal prevented") },
  689. /* P */{SST(0x54, 0x00, SS_RDEF,
  690. "Scsi to host system interface failure") },
  691. /* P */{SST(0x55, 0x00, SS_RDEF,
  692. "System resource failure") },
  693. /* D O */{SST(0x55, 0x01, SS_FATAL|ENOSPC,
  694. "System buffer full") },
  695. /* R */{SST(0x57, 0x00, SS_RDEF,
  696. "Unable to recover table-of-contents") },
  697. /* O */{SST(0x58, 0x00, SS_RDEF,
  698. "Generation does not exist") },
  699. /* O */{SST(0x59, 0x00, SS_RDEF,
  700. "Updated block read") },
  701. /* DTLPWRSOM */{SST(0x5A, 0x00, SS_RDEF,
  702. "Operator request or state change input") },
  703. /* DT WR OM */{SST(0x5A, 0x01, SS_RDEF,
  704. "Operator medium removal request") },
  705. /* DT W O */{SST(0x5A, 0x02, SS_RDEF,
  706. "Operator selected write protect") },
  707. /* DT W O */{SST(0x5A, 0x03, SS_RDEF,
  708. "Operator selected write permit") },
  709. /* DTLPWRSOM */{SST(0x5B, 0x00, SS_RDEF,
  710. "Log exception") },
  711. /* DTLPWRSOM */{SST(0x5B, 0x01, SS_RDEF,
  712. "Threshold condition met") },
  713. /* DTLPWRSOM */{SST(0x5B, 0x02, SS_RDEF,
  714. "Log counter at maximum") },
  715. /* DTLPWRSOM */{SST(0x5B, 0x03, SS_RDEF,
  716. "Log list codes exhausted") },
  717. /* D O */{SST(0x5C, 0x00, SS_RDEF,
  718. "RPL status change") },
  719. /* D O */{SST(0x5C, 0x01, SS_NOP|SSQ_PRINT_SENSE,
  720. "Spindles synchronized") },
  721. /* D O */{SST(0x5C, 0x02, SS_RDEF,
  722. "Spindles not synchronized") },
  723. /* DTLPWRSOMCAE */{SST(0x5D, 0x00, SS_RDEF,
  724. "Failure prediction threshold exceeded") },
  725. /* DTLPWRSOMCAE */{SST(0x5D, 0xFF, SS_RDEF,
  726. "Failure prediction threshold exceeded (false)") },
  727. /* DTLPWRSO CA */{SST(0x5E, 0x00, SS_RDEF,
  728. "Low power condition on") },
  729. /* DTLPWRSO CA */{SST(0x5E, 0x01, SS_RDEF,
  730. "Idle condition activated by timer") },
  731. /* DTLPWRSO CA */{SST(0x5E, 0x02, SS_RDEF,
  732. "Standby condition activated by timer") },
  733. /* DTLPWRSO CA */{SST(0x5E, 0x03, SS_RDEF,
  734. "Idle condition activated by command") },
  735. /* DTLPWRSO CA */{SST(0x5E, 0x04, SS_RDEF,
  736. "Standby condition activated by command") },
  737. /* S */{SST(0x60, 0x00, SS_RDEF,
  738. "Lamp failure") },
  739. /* S */{SST(0x61, 0x00, SS_RDEF,
  740. "Video acquisition error") },
  741. /* S */{SST(0x61, 0x01, SS_RDEF,
  742. "Unable to acquire video") },
  743. /* S */{SST(0x61, 0x02, SS_RDEF,
  744. "Out of focus") },
  745. /* S */{SST(0x62, 0x00, SS_RDEF,
  746. "Scan head positioning error") },
  747. /* R */{SST(0x63, 0x00, SS_RDEF,
  748. "End of user area encountered on this track") },
  749. /* R */{SST(0x63, 0x01, SS_FATAL|ENOSPC,
  750. "Packet does not fit in available space") },
  751. /* R */{SST(0x64, 0x00, SS_RDEF,
  752. "Illegal mode for this track") },
  753. /* R */{SST(0x64, 0x01, SS_RDEF,
  754. "Invalid packet size") },
  755. /* DTLPWRSOMCAE */{SST(0x65, 0x00, SS_RDEF,
  756. "Voltage fault") },
  757. /* S */{SST(0x66, 0x00, SS_RDEF,
  758. "Automatic document feeder cover up") },
  759. /* S */{SST(0x66, 0x01, SS_RDEF,
  760. "Automatic document feeder lift up") },
  761. /* S */{SST(0x66, 0x02, SS_RDEF,
  762. "Document jam in automatic document feeder") },
  763. /* S */{SST(0x66, 0x03, SS_RDEF,
  764. "Document miss feed automatic in document feeder") },
  765. /* A */{SST(0x67, 0x00, SS_RDEF,
  766. "Configuration failure") },
  767. /* A */{SST(0x67, 0x01, SS_RDEF,
  768. "Configuration of incapable logical units failed") },
  769. /* A */{SST(0x67, 0x02, SS_RDEF,
  770. "Add logical unit failed") },
  771. /* A */{SST(0x67, 0x03, SS_RDEF,
  772. "Modification of logical unit failed") },
  773. /* A */{SST(0x67, 0x04, SS_RDEF,
  774. "Exchange of logical unit failed") },
  775. /* A */{SST(0x67, 0x05, SS_RDEF,
  776. "Remove of logical unit failed") },
  777. /* A */{SST(0x67, 0x06, SS_RDEF,
  778. "Attachment of logical unit failed") },
  779. /* A */{SST(0x67, 0x07, SS_RDEF,
  780. "Creation of logical unit failed") },
  781. /* A */{SST(0x68, 0x00, SS_RDEF,
  782. "Logical unit not configured") },
  783. /* A */{SST(0x69, 0x00, SS_RDEF,
  784. "Data loss on logical unit") },
  785. /* A */{SST(0x69, 0x01, SS_RDEF,
  786. "Multiple logical unit failures") },
  787. /* A */{SST(0x69, 0x02, SS_RDEF,
  788. "Parity/data mismatch") },
  789. /* A */{SST(0x6A, 0x00, SS_RDEF,
  790. "Informational, refer to log") },
  791. /* A */{SST(0x6B, 0x00, SS_RDEF,
  792. "State change has occurred") },
  793. /* A */{SST(0x6B, 0x01, SS_RDEF,
  794. "Redundancy level got better") },
  795. /* A */{SST(0x6B, 0x02, SS_RDEF,
  796. "Redundancy level got worse") },
  797. /* A */{SST(0x6C, 0x00, SS_RDEF,
  798. "Rebuild failure occurred") },
  799. /* A */{SST(0x6D, 0x00, SS_RDEF,
  800. "Recalculate failure occurred") },
  801. /* A */{SST(0x6E, 0x00, SS_RDEF,
  802. "Command to logical unit failed") },
  803. /* T */{SST(0x70, 0x00, SS_RDEF,
  804. "Decompression exception short: ASCQ = Algorithm ID") },
  805. /* T */{SST(0x70, 0xFF, SS_RDEF|SSQ_RANGE,
  806. NULL) }, /* Range 0x00 -> 0xFF */
  807. /* T */{SST(0x71, 0x00, SS_RDEF,
  808. "Decompression exception long: ASCQ = Algorithm ID") },
  809. /* T */{SST(0x71, 0xFF, SS_RDEF|SSQ_RANGE,
  810. NULL) }, /* Range 0x00 -> 0xFF */
  811. /* R */{SST(0x72, 0x00, SS_RDEF,
  812. "Session fixation error") },
  813. /* R */{SST(0x72, 0x01, SS_RDEF,
  814. "Session fixation error writing lead-in") },
  815. /* R */{SST(0x72, 0x02, SS_RDEF,
  816. "Session fixation error writing lead-out") },
  817. /* R */{SST(0x72, 0x03, SS_RDEF,
  818. "Session fixation error - incomplete track in session") },
  819. /* R */{SST(0x72, 0x04, SS_RDEF,
  820. "Empty or partially written reserved track") },
  821. /* R */{SST(0x73, 0x00, SS_RDEF,
  822. "CD control error") },
  823. /* R */{SST(0x73, 0x01, SS_RDEF,
  824. "Power calibration area almost full") },
  825. /* R */{SST(0x73, 0x02, SS_FATAL|ENOSPC,
  826. "Power calibration area is full") },
  827. /* R */{SST(0x73, 0x03, SS_RDEF,
  828. "Power calibration area error") },
  829. /* R */{SST(0x73, 0x04, SS_RDEF,
  830. "Program memory area update failure") },
  831. /* R */{SST(0x73, 0x05, SS_RDEF,
  832. "program memory area is full") }
  833. };
  834. static const int asc_table_size = sizeof(asc_table)/sizeof(asc_table[0]);
  835. struct asc_key
  836. {
  837. int asc;
  838. int ascq;
  839. };
  840. static int
  841. ascentrycomp(const void *key, const void *member)
  842. {
  843. int asc;
  844. int ascq;
  845. const struct asc_table_entry *table_entry;
  846. asc = ((const struct asc_key *)key)->asc;
  847. ascq = ((const struct asc_key *)key)->ascq;
  848. table_entry = (const struct asc_table_entry *)member;
  849. if (asc >= table_entry->asc) {
  850. if (asc > table_entry->asc)
  851. return (1);
  852. if (ascq <= table_entry->ascq) {
  853. /* Check for ranges */
  854. if (ascq == table_entry->ascq
  855. || ((table_entry->action & SSQ_RANGE) != 0
  856. && ascq >= (table_entry - 1)->ascq))
  857. return (0);
  858. return (-1);
  859. }
  860. return (1);
  861. }
  862. return (-1);
  863. }
  864. static int
  865. senseentrycomp(const void *key, const void *member)
  866. {
  867. int sense_key;
  868. const struct sense_key_table_entry *table_entry;
  869. sense_key = *((const int *)key);
  870. table_entry = (const struct sense_key_table_entry *)member;
  871. if (sense_key >= table_entry->sense_key) {
  872. if (sense_key == table_entry->sense_key)
  873. return (0);
  874. return (1);
  875. }
  876. return (-1);
  877. }
  878. static void
  879. fetchtableentries(int sense_key, int asc, int ascq,
  880. struct scsi_inquiry_data *inq_data,
  881. const struct sense_key_table_entry **sense_entry,
  882. const struct asc_table_entry **asc_entry)
  883. {
  884. void *match;
  885. const struct asc_table_entry *asc_tables[2];
  886. const struct sense_key_table_entry *sense_tables[2];
  887. struct asc_key asc_ascq;
  888. size_t asc_tables_size[2];
  889. size_t sense_tables_size[2];
  890. int num_asc_tables;
  891. int num_sense_tables;
  892. int i;
  893. /* Default to failure */
  894. *sense_entry = NULL;
  895. *asc_entry = NULL;
  896. match = NULL;
  897. if (inq_data != NULL)
  898. match = cam_quirkmatch((void *)inq_data,
  899. (void *)sense_quirk_table,
  900. sense_quirk_table_size,
  901. sizeof(*sense_quirk_table),
  902. aic_inquiry_match);
  903. if (match != NULL) {
  904. struct scsi_sense_quirk_entry *quirk;
  905. quirk = (struct scsi_sense_quirk_entry *)match;
  906. asc_tables[0] = quirk->asc_info;
  907. asc_tables_size[0] = quirk->num_ascs;
  908. asc_tables[1] = asc_table;
  909. asc_tables_size[1] = asc_table_size;
  910. num_asc_tables = 2;
  911. sense_tables[0] = quirk->sense_key_info;
  912. sense_tables_size[0] = quirk->num_sense_keys;
  913. sense_tables[1] = sense_key_table;
  914. sense_tables_size[1] = sense_key_table_size;
  915. num_sense_tables = 2;
  916. } else {
  917. asc_tables[0] = asc_table;
  918. asc_tables_size[0] = asc_table_size;
  919. num_asc_tables = 1;
  920. sense_tables[0] = sense_key_table;
  921. sense_tables_size[0] = sense_key_table_size;
  922. num_sense_tables = 1;
  923. }
  924. asc_ascq.asc = asc;
  925. asc_ascq.ascq = ascq;
  926. for (i = 0; i < num_asc_tables; i++) {
  927. void *found_entry;
  928. found_entry = scsibsearch(&asc_ascq, asc_tables[i],
  929. asc_tables_size[i],
  930. sizeof(**asc_tables),
  931. ascentrycomp);
  932. if (found_entry) {
  933. *asc_entry = (struct asc_table_entry *)found_entry;
  934. break;
  935. }
  936. }
  937. for (i = 0; i < num_sense_tables; i++) {
  938. void *found_entry;
  939. found_entry = scsibsearch(&sense_key, sense_tables[i],
  940. sense_tables_size[i],
  941. sizeof(**sense_tables),
  942. senseentrycomp);
  943. if (found_entry) {
  944. *sense_entry =
  945. (struct sense_key_table_entry *)found_entry;
  946. break;
  947. }
  948. }
  949. }
  950. static void *
  951. scsibsearch(const void *key, const void *base, size_t nmemb, size_t size,
  952. int (*compar)(const void *, const void *))
  953. {
  954. const void *entry;
  955. u_int l;
  956. u_int u;
  957. u_int m;
  958. l = -1;
  959. u = nmemb;
  960. while (l + 1 != u) {
  961. m = (l + u) / 2;
  962. entry = base + m * size;
  963. if (compar(key, entry) > 0)
  964. l = m;
  965. else
  966. u = m;
  967. }
  968. entry = base + u * size;
  969. if (u == nmemb
  970. || compar(key, entry) != 0)
  971. return (NULL);
  972. return ((void *)entry);
  973. }
  974. /*
  975. * Compare string with pattern, returning 0 on match.
  976. * Short pattern matches trailing blanks in name,
  977. * wildcard '*' in pattern matches rest of name,
  978. * wildcard '?' matches a single non-space character.
  979. */
  980. static int
  981. cam_strmatch(const uint8_t *str, const uint8_t *pattern, int str_len)
  982. {
  983. while (*pattern != '\0'&& str_len > 0) {
  984. if (*pattern == '*') {
  985. return (0);
  986. }
  987. if ((*pattern != *str)
  988. && (*pattern != '?' || *str == ' ')) {
  989. return (1);
  990. }
  991. pattern++;
  992. str++;
  993. str_len--;
  994. }
  995. while (str_len > 0 && *str++ == ' ')
  996. str_len--;
  997. return (str_len);
  998. }
  999. static caddr_t
  1000. cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
  1001. int entry_size, cam_quirkmatch_t *comp_func)
  1002. {
  1003. for (; num_entries > 0; num_entries--, quirk_table += entry_size) {
  1004. if ((*comp_func)(target, quirk_table) == 0)
  1005. return (quirk_table);
  1006. }
  1007. return (NULL);
  1008. }
  1009. void
  1010. aic_sense_desc(int sense_key, int asc, int ascq,
  1011. struct scsi_inquiry_data *inq_data,
  1012. const char **sense_key_desc, const char **asc_desc)
  1013. {
  1014. const struct asc_table_entry *asc_entry;
  1015. const struct sense_key_table_entry *sense_entry;
  1016. fetchtableentries(sense_key, asc, ascq,
  1017. inq_data,
  1018. &sense_entry,
  1019. &asc_entry);
  1020. *sense_key_desc = sense_entry->desc;
  1021. if (asc_entry != NULL)
  1022. *asc_desc = asc_entry->desc;
  1023. else if (asc >= 0x80 && asc <= 0xff)
  1024. *asc_desc = "Vendor Specific ASC";
  1025. else if (ascq >= 0x80 && ascq <= 0xff)
  1026. *asc_desc = "Vendor Specific ASCQ";
  1027. else
  1028. *asc_desc = "Reserved ASC/ASCQ pair";
  1029. }
  1030. /*
  1031. * Given sense and device type information, return the appropriate action.
  1032. * If we do not understand the specific error as identified by the ASC/ASCQ
  1033. * pair, fall back on the more generic actions derived from the sense key.
  1034. */
  1035. aic_sense_action
  1036. aic_sense_error_action(struct scsi_sense_data *sense_data,
  1037. struct scsi_inquiry_data *inq_data, uint32_t sense_flags)
  1038. {
  1039. const struct asc_table_entry *asc_entry;
  1040. const struct sense_key_table_entry *sense_entry;
  1041. int error_code, sense_key, asc, ascq;
  1042. aic_sense_action action;
  1043. scsi_extract_sense(sense_data, &error_code, &sense_key, &asc, &ascq);
  1044. if (error_code == SSD_DEFERRED_ERROR) {
  1045. /*
  1046. * XXX dufault@FreeBSD.org
  1047. * This error doesn't relate to the command associated
  1048. * with this request sense. A deferred error is an error
  1049. * for a command that has already returned GOOD status
  1050. * (see SCSI2 8.2.14.2).
  1051. *
  1052. * By my reading of that section, it looks like the current
  1053. * command has been cancelled, we should now clean things up
  1054. * (hopefully recovering any lost data) and then retry the
  1055. * current command. There are two easy choices, both wrong:
  1056. *
  1057. * 1. Drop through (like we had been doing), thus treating
  1058. * this as if the error were for the current command and
  1059. * return and stop the current command.
  1060. *
  1061. * 2. Issue a retry (like I made it do) thus hopefully
  1062. * recovering the current transfer, and ignoring the
  1063. * fact that we've dropped a command.
  1064. *
  1065. * These should probably be handled in a device specific
  1066. * sense handler or punted back up to a user mode daemon
  1067. */
  1068. action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE;
  1069. } else {
  1070. fetchtableentries(sense_key, asc, ascq,
  1071. inq_data,
  1072. &sense_entry,
  1073. &asc_entry);
  1074. /*
  1075. * Override the 'No additional Sense' entry (0,0)
  1076. * with the error action of the sense key.
  1077. */
  1078. if (asc_entry != NULL
  1079. && (asc != 0 || ascq != 0))
  1080. action = asc_entry->action;
  1081. else
  1082. action = sense_entry->action;
  1083. if (sense_key == SSD_KEY_RECOVERED_ERROR) {
  1084. /*
  1085. * The action succeeded but the device wants
  1086. * the user to know that some recovery action
  1087. * was required.
  1088. */
  1089. action &= ~(SS_MASK|SSQ_MASK|SS_ERRMASK);
  1090. action |= SS_NOP|SSQ_PRINT_SENSE;
  1091. } else if (sense_key == SSD_KEY_ILLEGAL_REQUEST) {
  1092. if ((sense_flags & SF_QUIET_IR) != 0)
  1093. action &= ~SSQ_PRINT_SENSE;
  1094. } else if (sense_key == SSD_KEY_UNIT_ATTENTION) {
  1095. if ((sense_flags & SF_RETRY_UA) != 0
  1096. && (action & SS_MASK) == SS_FAIL) {
  1097. action &= ~(SS_MASK|SSQ_MASK);
  1098. action |= SS_RETRY|SSQ_DECREMENT_COUNT|
  1099. SSQ_PRINT_SENSE;
  1100. }
  1101. }
  1102. }
  1103. if ((sense_flags & SF_PRINT_ALWAYS) != 0)
  1104. action |= SSQ_PRINT_SENSE;
  1105. else if ((sense_flags & SF_NO_PRINT) != 0)
  1106. action &= ~SSQ_PRINT_SENSE;
  1107. return (action);
  1108. }
  1109. /*
  1110. * Try make as good a match as possible with
  1111. * available sub drivers
  1112. */
  1113. int
  1114. aic_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
  1115. {
  1116. struct scsi_inquiry_pattern *entry;
  1117. struct scsi_inquiry_data *inq;
  1118. entry = (struct scsi_inquiry_pattern *)table_entry;
  1119. inq = (struct scsi_inquiry_data *)inqbuffer;
  1120. if (((SID_TYPE(inq) == entry->type)
  1121. || (entry->type == T_ANY))
  1122. && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
  1123. : entry->media_type & SIP_MEDIA_FIXED)
  1124. && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
  1125. && (cam_strmatch(inq->product, entry->product,
  1126. sizeof(inq->product)) == 0)
  1127. && (cam_strmatch(inq->revision, entry->revision,
  1128. sizeof(inq->revision)) == 0)) {
  1129. return (0);
  1130. }
  1131. return (-1);
  1132. }
  1133. /*
  1134. * Table of syncrates that don't follow the "divisible by 4"
  1135. * rule. This table will be expanded in future SCSI specs.
  1136. */
  1137. static struct {
  1138. u_int period_factor;
  1139. u_int period; /* in 100ths of ns */
  1140. } scsi_syncrates[] = {
  1141. { 0x08, 625 }, /* FAST-160 */
  1142. { 0x09, 1250 }, /* FAST-80 */
  1143. { 0x0a, 2500 }, /* FAST-40 40MHz */
  1144. { 0x0b, 3030 }, /* FAST-40 33MHz */
  1145. { 0x0c, 5000 } /* FAST-20 */
  1146. };
  1147. /*
  1148. * Return the frequency in kHz corresponding to the given
  1149. * sync period factor.
  1150. */
  1151. u_int
  1152. aic_calc_syncsrate(u_int period_factor)
  1153. {
  1154. int i;
  1155. int num_syncrates;
  1156. num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
  1157. /* See if the period is in the "exception" table */
  1158. for (i = 0; i < num_syncrates; i++) {
  1159. if (period_factor == scsi_syncrates[i].period_factor) {
  1160. /* Period in kHz */
  1161. return (100000000 / scsi_syncrates[i].period);
  1162. }
  1163. }
  1164. /*
  1165. * Wasn't in the table, so use the standard
  1166. * 4 times conversion.
  1167. */
  1168. return (10000000 / (period_factor * 4 * 10));
  1169. }
  1170. /*
  1171. * Return speed in KB/s.
  1172. */
  1173. u_int
  1174. aic_calc_speed(u_int width, u_int period, u_int offset, u_int min_rate)
  1175. {
  1176. u_int freq;
  1177. if (offset != 0 && period < min_rate)
  1178. freq = aic_calc_syncsrate(period);
  1179. else
  1180. /* Roughly 3.3MB/s for async */
  1181. freq = 3300;
  1182. freq <<= width;
  1183. return (freq);
  1184. }
  1185. uint32_t
  1186. aic_error_action(struct scsi_cmnd *cmd, struct scsi_inquiry_data *inq_data,
  1187. cam_status status, u_int scsi_status)
  1188. {
  1189. aic_sense_action err_action;
  1190. int sense;
  1191. sense = (cmd->result >> 24) == DRIVER_SENSE;
  1192. switch (status) {
  1193. case CAM_REQ_CMP:
  1194. err_action = SS_NOP;
  1195. break;
  1196. case CAM_AUTOSENSE_FAIL:
  1197. case CAM_SCSI_STATUS_ERROR:
  1198. switch (scsi_status) {
  1199. case SCSI_STATUS_OK:
  1200. case SCSI_STATUS_COND_MET:
  1201. case SCSI_STATUS_INTERMED:
  1202. case SCSI_STATUS_INTERMED_COND_MET:
  1203. err_action = SS_NOP;
  1204. break;
  1205. case SCSI_STATUS_CMD_TERMINATED:
  1206. case SCSI_STATUS_CHECK_COND:
  1207. if (sense != 0) {
  1208. struct scsi_sense_data *sense;
  1209. sense = (struct scsi_sense_data *)
  1210. &cmd->sense_buffer;
  1211. err_action =
  1212. aic_sense_error_action(sense, inq_data, 0);
  1213. } else {
  1214. err_action = SS_RETRY|SSQ_FALLBACK
  1215. | SSQ_DECREMENT_COUNT|EIO;
  1216. }
  1217. break;
  1218. case SCSI_STATUS_QUEUE_FULL:
  1219. case SCSI_STATUS_BUSY:
  1220. err_action = SS_RETRY|SSQ_DELAY|SSQ_MANY
  1221. | SSQ_DECREMENT_COUNT|EBUSY;
  1222. break;
  1223. case SCSI_STATUS_RESERV_CONFLICT:
  1224. default:
  1225. err_action = SS_FAIL|EBUSY;
  1226. break;
  1227. }
  1228. break;
  1229. case CAM_CMD_TIMEOUT:
  1230. case CAM_REQ_CMP_ERR:
  1231. case CAM_UNEXP_BUSFREE:
  1232. case CAM_UNCOR_PARITY:
  1233. case CAM_DATA_RUN_ERR:
  1234. err_action = SS_RETRY|SSQ_FALLBACK|EIO;
  1235. break;
  1236. case CAM_UA_ABORT:
  1237. case CAM_UA_TERMIO:
  1238. case CAM_MSG_REJECT_REC:
  1239. case CAM_SEL_TIMEOUT:
  1240. err_action = SS_FAIL|EIO;
  1241. break;
  1242. case CAM_REQ_INVALID:
  1243. case CAM_PATH_INVALID:
  1244. case CAM_DEV_NOT_THERE:
  1245. case CAM_NO_HBA:
  1246. case CAM_PROVIDE_FAIL:
  1247. case CAM_REQ_TOO_BIG:
  1248. case CAM_RESRC_UNAVAIL:
  1249. case CAM_BUSY:
  1250. default:
  1251. /* panic?? These should never occur in our application. */
  1252. err_action = SS_FAIL|EIO;
  1253. break;
  1254. case CAM_SCSI_BUS_RESET:
  1255. case CAM_BDR_SENT:
  1256. case CAM_REQUEUE_REQ:
  1257. /* Unconditional requeue */
  1258. err_action = SS_RETRY;
  1259. break;
  1260. }
  1261. return (err_action);
  1262. }
  1263. char *
  1264. aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
  1265. aic_option_callback_t *callback, u_long callback_arg)
  1266. {
  1267. char *tok_end;
  1268. char *tok_end2;
  1269. int i;
  1270. int instance;
  1271. int targ;
  1272. int done;
  1273. char tok_list[] = {'.', ',', '{', '}', '\0'};
  1274. /* All options use a ':' name/arg separator */
  1275. if (*opt_arg != ':')
  1276. return (opt_arg);
  1277. opt_arg++;
  1278. instance = -1;
  1279. targ = -1;
  1280. done = FALSE;
  1281. /*
  1282. * Restore separator that may be in
  1283. * the middle of our option argument.
  1284. */
  1285. tok_end = strchr(opt_arg, '\0');
  1286. if (tok_end < end)
  1287. *tok_end = ',';
  1288. while (!done) {
  1289. switch (*opt_arg) {
  1290. case '{':
  1291. if (instance == -1) {
  1292. instance = 0;
  1293. } else {
  1294. if (depth > 1) {
  1295. if (targ == -1)
  1296. targ = 0;
  1297. } else {
  1298. printf("Malformed Option %s\n",
  1299. opt_name);
  1300. done = TRUE;
  1301. }
  1302. }
  1303. opt_arg++;
  1304. break;
  1305. case '}':
  1306. if (targ != -1)
  1307. targ = -1;
  1308. else if (instance != -1)
  1309. instance = -1;
  1310. opt_arg++;
  1311. break;
  1312. case ',':
  1313. case '.':
  1314. if (instance == -1)
  1315. done = TRUE;
  1316. else if (targ >= 0)
  1317. targ++;
  1318. else if (instance >= 0)
  1319. instance++;
  1320. opt_arg++;
  1321. break;
  1322. case '\0':
  1323. done = TRUE;
  1324. break;
  1325. default:
  1326. tok_end = end;
  1327. for (i = 0; tok_list[i]; i++) {
  1328. tok_end2 = strchr(opt_arg, tok_list[i]);
  1329. if ((tok_end2) && (tok_end2 < tok_end))
  1330. tok_end = tok_end2;
  1331. }
  1332. callback(callback_arg, instance, targ,
  1333. simple_strtol(opt_arg, NULL, 0));
  1334. opt_arg = tok_end;
  1335. break;
  1336. }
  1337. }
  1338. return (opt_arg);
  1339. }