1 /* 2 * Copyright (c) 1992 Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Ralph Campbell. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)scsi.c 7.1 (Berkeley) 01/07/92 11 */ 12 13 /* 14 * SCSI utility routines for making SCSI device drivers easier. 15 */ 16 17 #include "param.h" 18 19 #include "device.h" 20 #include "scsi.h" 21 22 /* 23 * The error codes for class 0-6 sense data are class specific. 24 * The follow arrays of strings are used to print error messages. 25 */ 26 static char *Class0Errors[] = { 27 "No sense data", 28 "No index signal", 29 "No seek complete", 30 "Write fault", 31 "Drive not ready", 32 "Drive not selected", 33 "No Track 00", 34 "Multiple drives selected", 35 "No address acknowledged", 36 "Media not loaded", 37 "Insufficient capacity", 38 "Drive timeout", 39 }; 40 static char *Class1Errors[] = { 41 "ID CRC error", 42 "Unrecoverable data error", 43 "ID address mark not found", 44 "Data address mark not found", 45 "Record not found", 46 "Seek error", 47 "DMA timeout error", 48 "Write protected", 49 "Correctable data check", 50 "Bad block found", 51 "Interleave error", 52 "Data transfer incomplete", 53 "Unformatted or bad format on drive", 54 "Self test failed", 55 "Defective track (media errors)", 56 }; 57 static char *Class2Errors[] = { 58 "Invalid command", 59 "Illegal block address", 60 "Aborted", 61 "Volume overflow", 62 }; 63 static char *Class7Errors[] = { 64 "No sense data", 65 "Recoverable error", 66 "Drive not ready", 67 "Media error", 68 "Hardware error", 69 "Illegal request", 70 "Unit attention", 71 "Write protected", 72 "Blank check error", 73 "Vendor error", 74 "Powerup failure", 75 "Abort", 76 "Equal", 77 "Overflow", 78 "Reserved14/miscompare", 79 }; 80 static int scsiNumErrors[] = { 81 sizeof(Class0Errors) / sizeof(char *), 82 sizeof(Class1Errors) / sizeof(char *), 83 sizeof(Class2Errors) / sizeof(char *), 84 0, 0, 0, 0, 0, 85 }; 86 static char **scsiErrors[] = { 87 Class0Errors, 88 Class1Errors, 89 Class2Errors, 90 }; 91 92 /* 93 * Decode the sense data and print a suitable message. 94 */ 95 scsiPrintSense(sp, len) 96 register ScsiClass7Sense *sp; 97 int len; 98 { 99 ScsiClass0Sense *sp0; 100 int class, code; 101 102 if (sp->error7 != 0x70) { 103 sp0 = (ScsiClass0Sense *)sp; 104 class = sp0->error >> 4; 105 code = sp0->error & 0xF; 106 if (code >= scsiNumErrors[class]) 107 printf("sense error 0x%x", sp0->error); 108 else 109 printf("%s", scsiErrors[class][code]); 110 if (sp->valid) 111 printf(", blk %d", (sp0->highAddr << 16) | 112 (sp0->midAddr << 8) | sp0->lowAddr); 113 } else { 114 if (sp->key >= sizeof(Class7Errors) / sizeof(char *)) 115 printf("sense class 7 error 0x%x", sp->key); 116 else 117 printf("%s", Class7Errors[sp->key]); 118 if (sp->valid) 119 printf(", blk %d", (sp->info1 << 24) | 120 (sp->info2 << 16) | (sp->info3 << 8) | 121 sp->info4); 122 } 123 printf("\n"); 124 } 125 126 /* 127 * Setup a command block for a SCSI Group0 command. 128 */ 129 void 130 scsiGroup0Cmd(cmd, lun, block, count, c) 131 unsigned cmd; /* group0 SCSI command */ 132 unsigned lun; /* Logical Unit Number */ 133 register unsigned block; /* starting block number for transfer */ 134 unsigned count; /* # of sectors/bytes to transfer */ 135 register ScsiGroup0Cmd *c; /* command to be filled in */ 136 { 137 138 c->command = cmd; 139 c->unitNumber = lun; 140 c->highAddr = block >> 16; 141 c->midAddr = block >> 8; 142 c->lowAddr = block; 143 c->blockCount = count; 144 c->control = 0; 145 } 146 147 /* 148 * Setup a command block for a SCSI Group1 command. 149 */ 150 void 151 scsiGroup1Cmd(cmd, lun, block, count, c) 152 unsigned cmd; /* group0 SCSI command */ 153 unsigned lun; /* Logical Unit Number */ 154 register unsigned block; /* starting block number for transfer */ 155 unsigned count; /* # of sectors/bytes to transfer */ 156 register ScsiGroup1Cmd *c; /* command to be filled in */ 157 { 158 159 c->command = cmd; 160 c->unitNumber = lun; 161 c->pad1 = 0; 162 c->highAddr = block >> 24; 163 c->midHighAddr = block >> 16; 164 c->midLowAddr = block >> 8; 165 c->lowAddr = block; 166 c->pad2 = 0; 167 c->highBlockCount = count >> 8; 168 c->lowBlockCount = count; 169 c->control = 0; 170 } 171