1 /* $Id: scsi-device.c,v 1.8 2009/11/08 17:17:42 fredette Exp $ */
2
3 /* scsi/scsi-device.c - implementation of generic SCSI device support: */
4
5 /*
6 * Copyright (c) 2003 Matt Fredette
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Matt Fredette.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #include <tme/common.h>
37 _TME_RCSID("$Id: scsi-device.c,v 1.8 2009/11/08 17:17:42 fredette Exp $");
38
39 /* includes: */
40 #include <tme/scsi/scsi-device.h>
41 #include <tme/scsi/scsi-msg.h>
42 #include <tme/scsi/scsi-cdb.h>
43
44 /* macros: */
45
46 /* the callout flags: */
47 #define TME_SCSI_DEVICE_CALLOUT_CHECK (0)
48 #define TME_SCSI_DEVICE_CALLOUT_RUNNING TME_BIT(0)
49 #define TME_SCSI_DEVICE_CALLOUTS_MASK (-2)
50 #define TME_SCSI_DEVICE_CALLOUT_CYCLE TME_BIT(1)
51
52 /* the SCSI device callout function. it must be called with the mutex locked: */
53 static void
_tme_scsi_device_callout(struct tme_scsi_device * scsi_device,int new_callouts)54 _tme_scsi_device_callout(struct tme_scsi_device *scsi_device,
55 int new_callouts)
56 {
57 struct tme_scsi_connection *conn_scsi;
58 int callouts, later_callouts;
59 int rc;
60 tme_uint32_t events;
61 tme_uint32_t actions;
62 const struct tme_scsi_dma *dma;
63 struct tme_scsi_dma dma_buffer;
64
65 /* add in any new callouts: */
66 scsi_device->tme_scsi_device_callout_flags |= new_callouts;
67
68 /* if this function is already running in another thread, simply
69 return now. the other thread will do our work: */
70 if (scsi_device->tme_scsi_device_callout_flags
71 & TME_SCSI_DEVICE_CALLOUT_RUNNING) {
72 return;
73 }
74
75 /* callouts are now running: */
76 scsi_device->tme_scsi_device_callout_flags
77 |= TME_SCSI_DEVICE_CALLOUT_RUNNING;
78
79 /* assume that we won't need any later callouts: */
80 later_callouts = 0;
81
82 /* loop while callouts are needed: */
83 for (; ((callouts
84 = scsi_device->tme_scsi_device_callout_flags)
85 & TME_SCSI_DEVICE_CALLOUTS_MASK); ) {
86
87 /* clear the needed callouts: */
88 scsi_device->tme_scsi_device_callout_flags
89 = (callouts
90 & ~TME_SCSI_DEVICE_CALLOUTS_MASK);
91 callouts
92 &= TME_SCSI_DEVICE_CALLOUTS_MASK;
93
94 /* get this card's SCSI connection: */
95 conn_scsi = scsi_device->tme_scsi_device_connection;
96
97 /* if we need to call out a SCSI bus cycle: */
98 if (callouts & TME_SCSI_DEVICE_CALLOUT_CYCLE) {
99
100 /* if the bus is busy: */
101 if (scsi_device->tme_scsi_device_control
102 & TME_SCSI_SIGNAL_BSY) {
103
104 /* run a target information transfer phase DMA sequence: */
105 events = TME_SCSI_EVENT_NONE;
106 actions = TME_SCSI_ACTION_DMA_TARGET;
107 dma_buffer = scsi_device->tme_scsi_device_dma;
108 dma = &dma_buffer;
109 }
110
111 /* otherwise, the bus is not busy: */
112 else {
113
114 /* wait to be selected: */
115 events = TME_SCSI_EVENT_SELECTED | TME_SCSI_EVENT_IDS_SELF(TME_BIT(scsi_device->tme_scsi_device_id));
116 actions = TME_SCSI_ACTION_RESPOND_SELECTED;
117 dma = NULL;
118 }
119
120 /* unlock the mutex: */
121 tme_mutex_unlock(&scsi_device->tme_scsi_device_mutex);
122
123 /* do the callout: */
124 rc = (conn_scsi != NULL
125 ? ((*conn_scsi->tme_scsi_connection_cycle)
126 (conn_scsi,
127 scsi_device->tme_scsi_device_control,
128 0,
129 events,
130 actions,
131 dma))
132 : TME_OK);
133
134 /* lock the mutex: */
135 tme_mutex_lock(&scsi_device->tme_scsi_device_mutex);
136
137 /* if the callout was unsuccessful, remember that at some later
138 time this callout should be attempted again: */
139 if (rc != TME_OK) {
140 later_callouts |= TME_SCSI_DEVICE_CALLOUT_CYCLE;
141 }
142 }
143
144 }
145
146 /* put in any later callouts, and clear that callouts are running: */
147 scsi_device->tme_scsi_device_callout_flags = later_callouts;
148 }
149
150 /* when a device is the target, this enters a new bus phase: */
151 void
tme_scsi_device_target_phase(struct tme_scsi_device * scsi_device,tme_scsi_control_t control)152 tme_scsi_device_target_phase(struct tme_scsi_device *scsi_device,
153 tme_scsi_control_t control)
154 {
155 const char *info_type;
156
157 /* set the phase: */
158 scsi_device->tme_scsi_device_control = control;
159
160 /* if we are not freeing the bus: */
161 if (control & TME_SCSI_SIGNAL_BSY) {
162
163 /* assume that we will not dump the information transferred: */
164 info_type = NULL;
165
166 /* XXX parity? */
167
168 /* dispatch on the phase: */
169 switch (TME_SCSI_PHASE(control)) {
170
171 /* for the DATA_OUT and DATA_IN phases, we assume that
172 the caller has already set up the DMA structure: */
173 case TME_SCSI_PHASE_DATA_IN:
174 info_type = "DATA_IN";
175 /* FALLTHROUGH */
176 case TME_SCSI_PHASE_DATA_OUT:
177 break;
178
179 /* for the COMMAND phase, begin by transferring the
180 first byte of the CDB: */
181 case TME_SCSI_PHASE_COMMAND:
182 assert ((scsi_device->tme_scsi_device_dma.tme_scsi_dma_flags
183 & TME_SCSI_DMA_WIDTH)
184 == TME_SCSI_DMA_8BIT);
185 scsi_device->tme_scsi_device_dma.tme_scsi_dma_in
186 = &scsi_device->tme_scsi_device_cdb[0];
187 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
188 = 1;
189 break;
190
191 /* for the STATUS phase, transfer the status byte: */
192 case TME_SCSI_PHASE_STATUS:
193 assert ((scsi_device->tme_scsi_device_dma.tme_scsi_dma_flags
194 & TME_SCSI_DMA_WIDTH)
195 == TME_SCSI_DMA_8BIT);
196 scsi_device->tme_scsi_device_dma.tme_scsi_dma_out
197 = &scsi_device->tme_scsi_device_status;
198 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
199 = 1;
200 info_type = "STATUS";
201 break;
202
203 /* for the MESSAGE_OUT phase, begin by transferring the
204 first byte of the message: */
205 case TME_SCSI_PHASE_MESSAGE_OUT:
206 assert ((scsi_device->tme_scsi_device_dma.tme_scsi_dma_flags
207 & TME_SCSI_DMA_WIDTH)
208 == TME_SCSI_DMA_8BIT);
209 scsi_device->tme_scsi_device_dma.tme_scsi_dma_in
210 = &scsi_device->tme_scsi_device_msg[0];
211 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
212 = 1;
213 break;
214
215 /* for the MESSAGE_IN phase, transfer the entire message: */
216 case TME_SCSI_PHASE_MESSAGE_IN:
217 assert ((scsi_device->tme_scsi_device_dma.tme_scsi_dma_flags
218 & TME_SCSI_DMA_WIDTH)
219 == TME_SCSI_DMA_8BIT);
220 scsi_device->tme_scsi_device_dma.tme_scsi_dma_out
221 = &scsi_device->tme_scsi_device_msg[0];
222
223 /* the total message length depends on the message type: */
224
225 /* "The extended message length specifies the length in bytes of
226 the extended message code plus the extended message arguments
227 to follow. Therefore, the total length of the message is
228 equal to the extended message length plus two. A value of
229 zero for the extended message length indicates 256 bytes
230 follow." */
231 if (scsi_device->tme_scsi_device_msg[0]
232 == TME_SCSI_MSG_EXTENDED) {
233 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
234 = ((scsi_device->tme_scsi_device_msg[1]
235 == 0)
236 ? (2 + 256)
237 : (2 + scsi_device->tme_scsi_device_msg[1]));
238 }
239
240 else if (TME_SCSI_MSG_IS_2(scsi_device->tme_scsi_device_msg[0])) {
241 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
242 = 2;
243 }
244
245 else {
246 assert (TME_SCSI_MSG_IS_1(scsi_device->tme_scsi_device_msg[0]));
247 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
248 = 1;
249 }
250 info_type = "MESSAGE_IN";
251 break;
252
253 default:
254 abort();
255 }
256
257 /* if we can, dump up to 128 bytes of information: */
258 if (info_type != NULL) {
259 tme_log_start(&scsi_device->tme_scsi_device_element->tme_element_log_handle,
260 2000, TME_OK) {
261 unsigned int byte_i, count;
262 count = TME_MIN(scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid,
263 128);
264 tme_log_part(&scsi_device->tme_scsi_device_element->tme_element_log_handle,
265 "%s:", info_type);
266 for (byte_i = 0; byte_i < count ; byte_i++) {
267 tme_log_part(&scsi_device->tme_scsi_device_element->tme_element_log_handle,
268 " 0x%02x",
269 scsi_device->tme_scsi_device_dma.tme_scsi_dma_out[byte_i]);
270 }
271 if (count < scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid) {
272 tme_log_part(&scsi_device->tme_scsi_device_element->tme_element_log_handle,
273 " ...");
274 }
275 } tme_log_finish(&scsi_device->tme_scsi_device_element->tme_element_log_handle);
276 }
277 }
278 }
279
280 /* this handles a SCSI bus cycle: */
281 static int
_tme_scsi_device_cycle(struct tme_scsi_connection * conn_scsi,tme_scsi_control_t control_new,tme_scsi_data_t data,tme_uint32_t events,tme_uint32_t actions,const struct tme_scsi_dma * dma)282 _tme_scsi_device_cycle(struct tme_scsi_connection *conn_scsi,
283 tme_scsi_control_t control_new,
284 tme_scsi_data_t data,
285 tme_uint32_t events,
286 tme_uint32_t actions,
287 const struct tme_scsi_dma *dma)
288 {
289 struct tme_scsi_device *scsi_device;
290 int new_callouts;
291 tme_scsi_control_t control_old;
292 unsigned long count;
293 void (*do_cdb) _TME_P((struct tme_scsi_device *,
294 tme_scsi_control_t,
295 tme_scsi_control_t));
296
297 /* recover our device: */
298 scsi_device = conn_scsi->tme_scsi_connection.tme_connection_element->tme_element_private;
299
300 /* assume that we won't need any new callouts: */
301 new_callouts = 0;
302
303 /* lock the mutex: */
304 tme_mutex_lock(&scsi_device->tme_scsi_device_mutex);
305
306 /* get the last bus state: */
307 control_old = scsi_device->tme_scsi_device_control;
308
309 /* if we last knew the bus to be free, we must now be selected: */
310 if (!(control_old
311 & TME_SCSI_SIGNAL_BSY)) {
312
313 /* "SCSI devices indicate their ability to accommodate more than
314 the COMMAND COMPLETE message by asserting or responding to the
315 ATN signal. The initiator indicates this in the SELECTION
316 phase by asserting ATN prior to the SCSI bus condition of SEL
317 true, and BSY false. The target indicates its ability to
318 accommodate more messages by responding to the ATTENTION
319 condition with the MESSAGE OUT phase after going through the
320 SELECTION phase." */
321
322 /* XXX parity? */
323 scsi_device->tme_scsi_device_dma.tme_scsi_dma_flags
324 = TME_SCSI_DMA_8BIT;
325 tme_scsi_device_target_phase(scsi_device,
326 TME_SCSI_SIGNAL_BSY
327 | ((control_new
328 & TME_SCSI_SIGNAL_ATN)
329 ? TME_SCSI_PHASE_MESSAGE_OUT
330 : TME_SCSI_PHASE_COMMAND));
331
332 /* no LUN has been addressed yet: */
333 scsi_device->tme_scsi_device_addressed_lun
334 = -1;
335 }
336
337 /* otherwise, we had the bus in some phase: */
338 else {
339
340 /* if we didn't transfer all of the bytes we wanted, something
341 went wrong with the initiator - probably the bus was reset: */
342 assert (dma != NULL);
343 scsi_device->tme_scsi_device_dma = *dma;
344 if (scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid > 0) {
345
346 /* return to the bus-free phase: */
347 scsi_device->tme_scsi_device_control
348 = 0;
349
350 /* log the forced bus free: */
351 tme_log(&scsi_device->tme_scsi_device_element->tme_element_log_handle,
352 1000, TME_OK,
353 (&scsi_device->tme_scsi_device_element->tme_element_log_handle,
354 _("short transfer, control now 0x%04x, forced bus free"),
355 control_new));
356
357 /* XXX callback? */
358 }
359
360 /* otherwise, we did transfer all of the bytes we wanted: */
361 else {
362
363 /* dispatch on the previous bus phase: */
364 switch (TME_SCSI_PHASE(control_old)) {
365 case TME_SCSI_PHASE_MESSAGE_OUT:
366
367 /* calculate how many message bytes we have transferred: */
368 count = (scsi_device->tme_scsi_device_dma.tme_scsi_dma_in
369 - &scsi_device->tme_scsi_device_msg[0]);
370
371 /* dispatch on the first byte of the message: */
372
373 /* if this is an extended message: */
374 if (scsi_device->tme_scsi_device_msg[0]
375 == TME_SCSI_MSG_EXTENDED) {
376
377 /* if we have only received the first message byte, receive
378 the next byte, which will give us the total length of the
379 message: */
380 if (count == 1) {
381 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
382 = 1;
383 }
384
385 /* if we have received the second message byte, we now know
386 the total length of the message: */
387 else if (count == 2) {
388 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
389 = ((scsi_device->tme_scsi_device_msg[1]
390 == 0)
391 ? 256
392 : scsi_device->tme_scsi_device_msg[1]);
393 }
394
395 /* otherwise, we must have received all of the message: */
396 }
397
398 /* if this is a two-byte message: */
399 else if (TME_SCSI_MSG_IS_2(scsi_device->tme_scsi_device_msg[0])) {
400
401 /* if we have only received the first message byte,
402 receive the second message byte: */
403 if (count == 1) {
404 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
405 = 1;
406 }
407
408 /* otherwise, we must have received all of the message: */
409 }
410
411 /* otherwise, this must be a one-byte message, and we have
412 received all of it: */
413 else {
414 assert (TME_SCSI_MSG_IS_1(scsi_device->tme_scsi_device_msg[0]));
415 }
416
417 /* if we have received all of the message: */
418 if (scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid == 0) {
419
420 /* log the message: */
421 tme_log_start(&scsi_device->tme_scsi_device_element->tme_element_log_handle,
422 1000, TME_OK) {
423 unsigned int byte_i;
424 tme_log_part(&scsi_device->tme_scsi_device_element->tme_element_log_handle,
425 _("MESSAGE_OUT:"));
426 for (byte_i = 0; byte_i < count ; byte_i++) {
427 tme_log_part(&scsi_device->tme_scsi_device_element->tme_element_log_handle,
428 " 0x%02x",
429 scsi_device->tme_scsi_device_msg[byte_i]);
430 }
431 } tme_log_finish(&scsi_device->tme_scsi_device_element->tme_element_log_handle);
432
433 /* "Normally, the initiator negates ATN while REQ is true
434 and ACK is false during the last REQ/ACK handshake of the
435 MESSAGE OUT phase." */
436 tme_scsi_device_target_phase(scsi_device,
437 TME_SCSI_SIGNAL_BSY
438 | ((control_new
439 & TME_SCSI_SIGNAL_ATN)
440 ? TME_SCSI_PHASE_MESSAGE_OUT
441 : TME_SCSI_PHASE_COMMAND));
442
443 /* call out for the message: */
444 (*((scsi_device->tme_scsi_device_msg[0]
445 == TME_SCSI_MSG_EXTENDED)
446 ? (scsi_device->tme_scsi_device_do_msg_ext
447 [scsi_device->tme_scsi_device_msg[2]])
448 : (scsi_device->tme_scsi_device_do_msg
449 [TME_MIN(scsi_device->tme_scsi_device_msg[0],
450 TME_SCSI_MSG_IDENTIFY)])))
451 (scsi_device,
452 control_old,
453 control_new);
454 }
455
456 break;
457
458 case TME_SCSI_PHASE_COMMAND:
459
460 /* calculate how many message bytes we have transferred: */
461 count = (scsi_device->tme_scsi_device_dma.tme_scsi_dma_in
462 - &scsi_device->tme_scsi_device_cdb[0]);
463
464 /* if we have only transferred the first byte: */
465 if (count == 1) {
466
467 /* dispatch on the CDB group: */
468 switch (scsi_device->tme_scsi_device_cdb[0]
469 & TME_SCSI_CDB_GROUP_MASK) {
470
471 case TME_SCSI_CDB_GROUP_0:
472 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
473 = TME_SCSI_CDB_GROUP_0_LEN;
474 break;
475 case TME_SCSI_CDB_GROUP_1:
476 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
477 = TME_SCSI_CDB_GROUP_1_LEN;
478 break;
479 case TME_SCSI_CDB_GROUP_2:
480 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
481 = TME_SCSI_CDB_GROUP_2_LEN;
482 break;
483 case TME_SCSI_CDB_GROUP_4:
484 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
485 = TME_SCSI_CDB_GROUP_4_LEN;
486 break;
487 case TME_SCSI_CDB_GROUP_5:
488 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
489 = TME_SCSI_CDB_GROUP_5_LEN;
490 break;
491
492 case TME_SCSI_CDB_GROUP_3:
493 case TME_SCSI_CDB_GROUP_6:
494 case TME_SCSI_CDB_GROUP_7:
495 default:
496 abort();
497 }
498
499 /* we have already transferred the first byte of the CDB: */
500 scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid--;
501 break;
502 }
503
504 /* otherwise, we must have transferred all of the command: */
505 else {
506
507 /* log the CDB: */
508 tme_log_start(&scsi_device->tme_scsi_device_element->tme_element_log_handle,
509 1000, TME_OK) {
510 unsigned int byte_i;
511 tme_log_part(&scsi_device->tme_scsi_device_element->tme_element_log_handle,
512 _("CDB:"));
513 for (byte_i = 0; byte_i < count ; byte_i++) {
514 tme_log_part(&scsi_device->tme_scsi_device_element->tme_element_log_handle,
515 " 0x%02x",
516 scsi_device->tme_scsi_device_cdb[byte_i]);
517 }
518 } tme_log_finish(&scsi_device->tme_scsi_device_element->tme_element_log_handle);
519
520 /* if the addressed LUN is valid: */
521 if (((*scsi_device->tme_scsi_device_address_lun)
522 (scsi_device))
523 == TME_OK) {
524
525 /* if this command is illegal: */
526 do_cdb
527 = (scsi_device->tme_scsi_device_do_cdb
528 [scsi_device->tme_scsi_device_cdb[0]]);
529 if (__tme_predict_false(do_cdb == NULL)) {
530
531 /* use the illegal command handler: */
532 do_cdb = tme_scsi_device_cdb_illegal;
533 }
534
535 /* call out for the CDB: */
536 (*do_cdb)
537 (scsi_device,
538 control_old,
539 control_new);
540 }
541 }
542
543 break;
544
545 /* all of these phases just cause phase callbacks: */
546 case TME_SCSI_PHASE_STATUS:
547 case TME_SCSI_PHASE_MESSAGE_IN:
548 case TME_SCSI_PHASE_DATA_OUT:
549 case TME_SCSI_PHASE_DATA_IN:
550 (*scsi_device->tme_scsi_device_phase)
551 (scsi_device,
552 control_old,
553 control_new);
554 break;
555
556 default: abort();
557 }
558 }
559 }
560
561 /* call out a new SCSI cycle: */
562 new_callouts |= TME_SCSI_DEVICE_CALLOUT_CYCLE;
563
564 /* make any needed callouts: */
565 _tme_scsi_device_callout(scsi_device, new_callouts);
566
567 /* unlock the mutex: */
568 tme_mutex_unlock(&scsi_device->tme_scsi_device_mutex);
569
570 return (TME_OK);
571 }
572
573 /* when a device is the target, this frees the bus: */
_TME_SCSI_DEVICE_PHASE_DECL(tme_scsi_device_target_f)574 _TME_SCSI_DEVICE_PHASE_DECL(tme_scsi_device_target_f)
575 {
576 /* enter the BUS FREE phase: */
577 tme_scsi_device_target_phase(scsi_device,
578 0);
579
580 /* there is no next phase we will enter: */
581 scsi_device->tme_scsi_device_phase
582 = NULL;
583 }
584
585 /* when a device is the target, this runs the MESSAGE IN phase,
586 followed by the BUS FREE phase. the transmitted message must be
587 preset: */
_TME_SCSI_DEVICE_PHASE_DECL(tme_scsi_device_target_mf)588 _TME_SCSI_DEVICE_PHASE_DECL(tme_scsi_device_target_mf)
589 {
590 /* enter the MESSAGE IN phase: */
591 tme_scsi_device_target_phase(scsi_device,
592 TME_SCSI_SIGNAL_BSY
593 | TME_SCSI_PHASE_MESSAGE_IN);
594
595 /* the next phase we enter will be the BUS FREE phase: */
596 scsi_device->tme_scsi_device_phase
597 = tme_scsi_device_target_f;
598 }
599
600 /* when a device is the target, this runs the STATUS phase, followed
601 by the MESSAGE IN phase, followed by the BUS FREE phase. the
602 transmitted status and message must be preset: */
_TME_SCSI_DEVICE_PHASE_DECL(tme_scsi_device_target_smf)603 _TME_SCSI_DEVICE_PHASE_DECL(tme_scsi_device_target_smf)
604 {
605 /* enter the STATUS phase: */
606 tme_scsi_device_target_phase(scsi_device,
607 TME_SCSI_SIGNAL_BSY
608 | TME_SCSI_PHASE_STATUS);
609
610 /* the next phase we enter will be the MESSAGE IN phase: */
611 scsi_device->tme_scsi_device_phase
612 = tme_scsi_device_target_mf;
613 }
614
615 /* when a device is the target, this runs the DATA IN or DATA OUT
616 phase, followed by the STATUS phase, followed by the MESSAGE IN
617 phase, followed by the BUS FREE phase. the transmitted data,
618 status and message must be preset: */
_TME_SCSI_DEVICE_PHASE_DECL(tme_scsi_device_target_dsmf)619 _TME_SCSI_DEVICE_PHASE_DECL(tme_scsi_device_target_dsmf)
620 {
621 /* enter the DATA IN or DATA OUT phase, depending on how
622 DMA was set up: */
623 tme_scsi_device_target_phase(scsi_device,
624 TME_SCSI_SIGNAL_BSY
625 | ((scsi_device->tme_scsi_device_dma.tme_scsi_dma_in
626 != NULL)
627 ? TME_SCSI_PHASE_DATA_OUT
628 : TME_SCSI_PHASE_DATA_IN));
629
630 /* the next phase we enter will be the STATUS phase: */
631 scsi_device->tme_scsi_device_phase
632 = tme_scsi_device_target_smf;
633 }
634
635 /* when a device is the target, this runs a MESSAGE IN phase, followed
636 usually by a COMMAND phase (but possibly a MESSAGE OUT phase): */
_TME_SCSI_DEVICE_PHASE_DECL(tme_scsi_device_target_mc)637 _TME_SCSI_DEVICE_PHASE_DECL(tme_scsi_device_target_mc)
638 {
639
640 /* enter either the MESSAGE OUT phase or the COMMAND phase: */
641 tme_scsi_device_target_phase(scsi_device,
642 TME_SCSI_SIGNAL_BSY
643 | ((control_new
644 & TME_SCSI_SIGNAL_ATN)
645 ? TME_SCSI_PHASE_MESSAGE_OUT
646 : TME_SCSI_PHASE_COMMAND));
647
648 #ifndef NDEBUG
649 /* both the MESSAGE OUT and COMMAND phases have specific
650 dispatchers: */
651 scsi_device->tme_scsi_device_phase = NULL;
652 #endif /* !NDEBUG */
653 }
654
655 /* when a device is the target, this builds a simple extended sense
656 and returns an immediate CHECK CONDITION status to the initiator: */
657 void
tme_scsi_device_check_condition(struct tme_scsi_device * scsi_device,tme_uint8_t sense_key,tme_uint16_t sense_asc_ascq)658 tme_scsi_device_check_condition(struct tme_scsi_device *scsi_device,
659 tme_uint8_t sense_key,
660 tme_uint16_t sense_asc_ascq)
661 {
662 struct tme_scsi_device_sense *sense;
663 int lun;
664
665 /* get the addressed LUN: */
666 lun = scsi_device->tme_scsi_device_addressed_lun;
667
668 /* this target must support extended sense: */
669 assert (!scsi_device->tme_scsi_device_sense_no_extended);
670
671 /* form the sense: */
672 sense = &scsi_device->tme_scsi_device_sense[lun];
673
674 /* the error class and error code: */
675 sense->tme_scsi_device_sense_data[0]
676 = 0x70;
677
678 /* the sense key: */
679 sense->tme_scsi_device_sense_data[2]
680 = sense_key;
681
682 /* if there is no additional sense: */
683 if (sense_asc_ascq == TME_SCSI_SENSE_EXT_ASC_ASCQ_NONE) {
684
685 /* there is no additional sense length: */
686 sense->tme_scsi_device_sense_data[7] = 0x00;
687 }
688
689 /* otherwise, there is additional sense: */
690 else {
691
692 /* the additional sense length: */
693 sense->tme_scsi_device_sense_data[7]
694 = 0x06;
695
696 /* the additional sense code and additional sense code qualifier: */
697 sense->tme_scsi_device_sense_data[12] = (sense_asc_ascq >> 8);
698 sense->tme_scsi_device_sense_data[13] = sense_asc_ascq;
699 }
700
701 /* this sense is valid: */
702 sense->tme_scsi_device_sense_valid
703 = TRUE;
704
705 /* return the CHECK CONDITION status: */
706 tme_scsi_device_target_do_smf(scsi_device,
707 TME_SCSI_STATUS_CHECK_CONDITION,
708 TME_SCSI_MSG_CMD_COMPLETE);
709 }
710
711 /* this is the LUN addresser for LUN-aware devices: */
712 int
tme_scsi_device_address_lun_aware(struct tme_scsi_device * scsi_device)713 tme_scsi_device_address_lun_aware(struct tme_scsi_device *scsi_device)
714 {
715 struct tme_scsi_device_sense *sense;
716 int lun;
717
718 /* if an IDENTIFY message was sent, use that LUN: */
719 lun = scsi_device->tme_scsi_device_addressed_lun;
720
721 /* otherwise, get the LUN from bits 5-7 of the second
722 CDB byte: */
723 if (lun < 0) {
724 lun = (scsi_device->tme_scsi_device_cdb[1] >> 5);
725 scsi_device->tme_scsi_device_addressed_lun = lun;
726 }
727
728 /* if this LUN is not defined, and this isn't a REQUEST SENSE
729 or INQUIRY command: */
730 if (!(scsi_device->tme_scsi_device_luns
731 & TME_BIT(lun))
732 && (scsi_device->tme_scsi_device_cdb[0]
733 != TME_SCSI_CDB_REQUEST_SENSE)
734 && (scsi_device->tme_scsi_device_cdb[0]
735 != TME_SCSI_CDB_INQUIRY)) {
736
737 /* this target must support extended sense: */
738 assert (!scsi_device->tme_scsi_device_sense_no_extended);
739
740 /* form the ILLEGAL REQUEST sense: */
741 sense = &scsi_device->tme_scsi_device_sense[lun];
742
743 /* the error class and error code: */
744 sense->tme_scsi_device_sense_data[0]
745 = 0x70;
746
747 /* the ILLEGAL REQUEST sense key: */
748 sense->tme_scsi_device_sense_data[2]
749 = 0x05;
750
751 /* the additional sense length: */
752 sense->tme_scsi_device_sense_data[7]
753 = 0x00;
754
755 sense->tme_scsi_device_sense_valid
756 = TRUE;
757
758 /* return the CHECK CONDITION status: */
759 tme_scsi_device_target_do_smf(scsi_device,
760 TME_SCSI_STATUS_CHECK_CONDITION,
761 TME_SCSI_MSG_CMD_COMPLETE);
762 return (EINVAL);
763 }
764
765 return (TME_OK);
766 }
767
768 /* this is the LUN addresser for LUN-unaware devices: */
769 int
tme_scsi_device_address_lun_unaware(struct tme_scsi_device * scsi_device)770 tme_scsi_device_address_lun_unaware(struct tme_scsi_device *scsi_device)
771 {
772
773 /* we always force a LUN of zero: */
774 scsi_device->tme_scsi_device_addressed_lun = 0;
775
776 return (tme_scsi_device_address_lun_aware(scsi_device));
777 }
778
779 /* this makes a new connection: */
780 int
tme_scsi_device_connection_make(struct tme_connection * conn,unsigned int state)781 tme_scsi_device_connection_make(struct tme_connection *conn,
782 unsigned int state)
783 {
784 struct tme_scsi_device *scsi_device;
785 struct tme_scsi_connection *conn_scsi;
786
787 /* recover our device: */
788 scsi_device = conn->tme_connection_element->tme_element_private;
789
790 /* both sides must be SCSI connections: */
791 assert (conn->tme_connection_type
792 == TME_CONNECTION_SCSI);
793 assert (conn->tme_connection_other->tme_connection_type
794 == TME_CONNECTION_SCSI);
795
796 /* simple SCSI devices are always set up to answer calls across the
797 connection, so we only have to do work when the connection has
798 gone full, namely taking the other side of the connection: */
799 if (state == TME_CONNECTION_FULL) {
800
801 /* lock the mutex: */
802 tme_mutex_lock(&scsi_device->tme_scsi_device_mutex);
803
804 /* save our connection: */
805 conn_scsi
806 = ((struct tme_scsi_connection *)
807 conn->tme_connection_other);
808 scsi_device->tme_scsi_device_connection
809 = conn_scsi;
810
811 /* call out a SCSI bus cycle: */
812 scsi_device->tme_scsi_device_control = 0;
813 _tme_scsi_device_callout(scsi_device,
814 TME_SCSI_DEVICE_CALLOUT_CYCLE);
815
816 /* unlock the mutex: */
817 tme_mutex_unlock(&scsi_device->tme_scsi_device_mutex);
818 }
819
820 return (TME_OK);
821 }
822
823 /* this breaks a connection: */
824 int
tme_scsi_device_connection_break(struct tme_connection * conn,unsigned int state)825 tme_scsi_device_connection_break(struct tme_connection *conn, unsigned int state)
826 {
827 abort();
828 }
829
830 /* this makes a new connection side for a SCSI device: */
831 int
tme_scsi_device_connections_new(struct tme_element * element,const char * const * args,struct tme_connection ** _conns,char ** _output)832 tme_scsi_device_connections_new(struct tme_element *element,
833 const char * const *args,
834 struct tme_connection **_conns,
835 char **_output)
836 {
837 struct tme_scsi_device *scsi_device;
838 struct tme_scsi_connection *conn_scsi;
839 struct tme_connection *conn;
840
841 /* recover our device: */
842 scsi_device = (struct tme_scsi_device *) element->tme_element_private;
843
844 /* if this device isn't connected to a SCSI bus, make the new
845 connection side: */
846 if (scsi_device->tme_scsi_device_connection == NULL) {
847
848 /* create our side of a SCSI connection: */
849 conn_scsi = tme_new0(struct tme_scsi_connection, 1);
850 conn = &conn_scsi->tme_scsi_connection;
851
852 /* fill in the generic connection: */
853 conn->tme_connection_next = *_conns;
854 conn->tme_connection_type = TME_CONNECTION_SCSI;
855 conn->tme_connection_score = tme_scsi_connection_score;
856 conn->tme_connection_make = tme_scsi_device_connection_make;
857 conn->tme_connection_break = tme_scsi_device_connection_break;
858
859 /* fill in the SCSI connection: */
860 conn_scsi->tme_scsi_connection_cycle
861 = _tme_scsi_device_cycle;
862
863 /* return the connection side possibility: */
864 *_conns = conn;
865 }
866
867 return (TME_OK);
868 }
869
870 /* this initializes a new SCSI device: */
871 int
tme_scsi_device_new(struct tme_scsi_device * scsi_device,int id)872 tme_scsi_device_new(struct tme_scsi_device *scsi_device,
873 int id)
874 {
875 int i;
876
877 /* initialize the mutex: */
878 tme_mutex_init(&scsi_device->tme_scsi_device_mutex);
879
880 /* set the SCSI ID: */
881 scsi_device->tme_scsi_device_id = id;
882
883 /* initialize all of the message and CDB handlers to NULL: */
884 for (i = TME_ARRAY_ELS(scsi_device->tme_scsi_device_do_msg);
885 i-- > 0; ) {
886 scsi_device->tme_scsi_device_do_msg[i] = NULL;
887 }
888 for (i = TME_ARRAY_ELS(scsi_device->tme_scsi_device_do_cdb);
889 i-- > 0; ) {
890 scsi_device->tme_scsi_device_do_cdb[i] = NULL;
891 }
892
893 /* set the message handlers: */
894 TME_SCSI_DEVICE_DO_MSG(scsi_device,
895 TME_SCSI_MSG_CMD_COMPLETE,
896 tme_scsi_device_msg_cmd_complete);
897 TME_SCSI_DEVICE_DO_MSG(scsi_device,
898 TME_SCSI_MSG_SAVE_DATA_POINTER,
899 tme_scsi_device_msg_save_data_pointer);
900 TME_SCSI_DEVICE_DO_MSG(scsi_device,
901 TME_SCSI_MSG_RESTORE_POINTERS,
902 tme_scsi_device_msg_restore_pointers);
903 TME_SCSI_DEVICE_DO_MSG(scsi_device,
904 TME_SCSI_MSG_DISCONNECT,
905 tme_scsi_device_msg_disconnect);
906 TME_SCSI_DEVICE_DO_MSG(scsi_device,
907 TME_SCSI_MSG_INITIATOR_ERROR,
908 tme_scsi_device_msg_initiator_error);
909 TME_SCSI_DEVICE_DO_MSG(scsi_device,
910 TME_SCSI_MSG_ABORT,
911 tme_scsi_device_msg_abort);
912 TME_SCSI_DEVICE_DO_MSG(scsi_device,
913 TME_SCSI_MSG_MESSAGE_REJECT,
914 tme_scsi_device_msg_message_reject);
915 TME_SCSI_DEVICE_DO_MSG(scsi_device,
916 TME_SCSI_MSG_NOP,
917 tme_scsi_device_msg_nop);
918 TME_SCSI_DEVICE_DO_MSG(scsi_device,
919 TME_SCSI_MSG_PARITY_ERROR,
920 tme_scsi_device_msg_parity_error);
921 TME_SCSI_DEVICE_DO_MSG(scsi_device,
922 TME_SCSI_MSG_IDENTIFY,
923 tme_scsi_device_msg_identify);
924 TME_SCSI_DEVICE_DO_MSG_EXT(scsi_device,
925 TME_SCSI_MSG_EXT_SDTR,
926 tme_scsi_device_msg_target_reject);
927
928 /* set the "Group 0 Common Commands for All Device Types": */
929 TME_SCSI_DEVICE_DO_CDB(scsi_device,
930 TME_SCSI_CDB_TEST_UNIT_READY,
931 tme_scsi_device_cdb_tur);
932 TME_SCSI_DEVICE_DO_CDB(scsi_device,
933 TME_SCSI_CDB_REQUEST_SENSE,
934 tme_scsi_device_cdb_request_sense);
935 TME_SCSI_DEVICE_DO_CDB(scsi_device,
936 TME_SCSI_CDB_INQUIRY,
937 NULL);
938
939 /* assume that this device is LUN-aware: */
940 scsi_device->tme_scsi_device_address_lun
941 = tme_scsi_device_address_lun_aware;
942
943 return (TME_OK);
944 }
945