1 /* @(#)scsi-atari.c 1.3 09/07/13 Copyright 1997,2000,2009 J. Schilling */
2 #ifndef lint
3 static char __sccsid[] =
4 "@(#)scsi-atari.c 1.3 09/07/13 Copyright 1997,2000,2009 J. Schilling";
5 #endif
6 /*
7 * Interface for Atari generic SCSI implementation.
8 *
9 * Copyright (c) 1997, 2000, 2009 J. Schilling
10 * Atari systems support code written by Yvan Doyeux
11 *
12 *
13 * SCSIDRV driver is needed to enable libscg on Atari computers.
14 * I need to pass through assembler to avoid using of -mshort GCC option.
15 * Actually SCSIDRV requires real 16-bit word for several function arguments.
16 *
17 * If you are using HDDRIVER, it already includes the SCSIDRV programming interface,
18 * otherwise you must run SCSIDRV.PRG before.
19 *
20 * The following bus-numbers are reserved for this:
21 * 0 (ACSI)
22 * 1 (Standard SCSI: Falcon, TT, Medusa, MagicMac...)
23 * 2 (IDE in Atari-compatibles)
24 *
25 * For further information, see packages SCSIDRV.ZIP and CBHD502.ZIP.
26 *
27 * Warning: you may change this source, but if you do that
28 * you need to change the _scg_version and _scg_auth* string below.
29 * You may not return "schily" for an SCG_AUTHOR request anymore.
30 * Choose your name instead of "schily" and make clear that the version
31 * string is related to a modified source.
32 */
33 /*
34 * The contents of this file are subject to the terms of the
35 * Common Development and Distribution License, Version 1.0 only
36 * (the "License"). You may not use this file except in compliance
37 * with the License.
38 *
39 * See the file CDDL.Schily.txt in this distribution for details.
40 * A copy of the CDDL is also available via the Internet at
41 * http://www.opensource.org/licenses/cddl1.txt
42 *
43 * The following exceptions apply:
44 * CDDL �3.6 needs to be replaced by: "You may create a Larger Work by
45 * combining Covered Software with other code if all other code is governed by
46 * the terms of a license that is OSI approved (see www.opensource.org) and
47 * you may distribute the Larger Work as a single product. In such a case,
48 * You must make sure the requirements of this License are fulfilled for
49 * the Covered Software."
50 *
51 * When distributing Covered Code, include this CDDL HEADER in each
52 * file and include the License file CDDL.Schily.txt from this distribution.
53 */
54
55 #include <schily/stdio.h>
56 #include <schily/string.h>
57 #include <osbind.h>
58 #include <schily/signal.h>
59 #include <schily/stdlib.h>
60
61 #define cdecl
62
63 #define BOOLEAN long
64 #define BYTE char /* Signed byte */
65 #define UBYTE unsigned char /* Unsigned byte */
66 #define WORD short /* Signed word (16 bits) */
67 #define UWORD unsigned short /* Unsigned word */
68
69 #define SCSIRevision 0x0101
70
71 #define MAXBUSNO 31
72 #define MAX_SCSIDRV_HANDLE 32
73
74 #define MAX_SCG 3 /* Max # of SCSI controllers */
75 #define MAX_TGT 8
76 #define MAX_LUN 1
77
78 /*
79 * SCSIDRV return values
80 */
81 #define CHECKCONDITION 2L
82 #define NOSCSIERROR 0L
83 #define SELECTERROR -1L
84 #define STATUSERROR -2L
85 #define PHASEERROR -3L
86 #define BSYERROR -4L
87 #define BUSERROR -5L
88 #define TRANSERROR -6L
89 #define FREEERROR -7L
90 #define TIMEOUTERROR -8L
91 #define DATATOOLONG -9L
92 #define LINKERROR -10L
93 #define TIMEOUTARBIT -11L
94 #define PENDINGERROR -12L
95 #define PARITYERROR -13L
96
97 LOCAL char _scg_trans_version[] = "scsi-atari.c-1.3"; /* The version for this transport */
98 LOCAL char _scg_auth[] = "Yvan Doyeux";
99
100
101 typedef struct {
102 unsigned long hi;
103 unsigned long lo;
104 } DLONG;
105
106 typedef struct {
107 unsigned long BusIds;
108 BYTE resrvd[28];
109 } tPrivate;
110
111 typedef WORD *tHandle;
112
113 typedef struct {
114 tHandle Handle;
115 BYTE *Cmd;
116 UWORD CmdLen;
117 void *Buffer;
118 unsigned long TransferLen;
119 BYTE *SenseBuffer;
120 unsigned long Timeout;
121 UWORD Flags;
122 #define Disconnect 0x10
123 } tSCSICmd;
124 typedef tSCSICmd *tpSCSICmd;
125
126
127 typedef struct {
128 tPrivate Private;
129 char BusName[20];
130 UWORD BusNo;
131 UWORD Features;
132 #define cArbit 0x01
133 #define cAllCmds 0x02
134 #define cTargCtrl 0x04
135 #define cTarget 0x08
136 #define cCanDisconnect 0x10
137 #define cScatterGather 0x20
138 unsigned long MaxLen;
139 } tBusInfo;
140
141
142 typedef struct {
143 BYTE Private[32];
144 DLONG SCSIId;
145 } tDevInfo;
146
147
148 typedef struct ttargethandler {
149 struct ttargethandler *next;
150 BOOLEAN cdecl (*TSel) (WORD bus, UWORD CSB, UWORD CSD);
151 BOOLEAN cdecl (*TCmd) (WORD bus, BYTE *Cmd);
152 UWORD cdecl (*TCmdLen) (WORD bus, UWORD Cmd);
153 void cdecl (*TReset) (UWORD bus);
154 void cdecl (*TEOP) (UWORD bus);
155 void cdecl (*TPErr) (UWORD bus);
156 void cdecl (*TPMism) (UWORD bus);
157 void cdecl (*TBLoss) (UWORD bus);
158 void cdecl (*TUnknownInt) (UWORD bus);
159 } tTargetHandler;
160
161 typedef tTargetHandler *tpTargetHandler;
162
163 typedef BYTE tReqData[18];
164
165 typedef struct
166 {
167 UWORD Version;
168
169 /* Routinen als Initiator */
170 long cdecl (*In) (tpSCSICmd Parms);
171 long cdecl (*Out) (tpSCSICmd Parms);
172
173 long cdecl (*InquireSCSI) (WORD what, tBusInfo *Info);
174 #define cInqFirst 0
175 #define cInqNext 1
176 long cdecl (*InquireBus) (WORD what, WORD BusNo, tDevInfo *Dev);
177 long cdecl (*CheckDev) (WORD BusNo, const DLONG *SCSIId, char *Name, UWORD *Features);
178 long cdecl (*RescanBus) (WORD BusNo);
179 long cdecl (*Open) (WORD BusNo, const DLONG *SCSIId, unsigned long *MaxLen);
180 long cdecl (*Close) (tHandle handle);
181 long cdecl (*Error) (tHandle handle, WORD rwflag, WORD ErrNo);
182 #define cErrRead 0
183 #define cErrWrite 1
184 #define cErrMediach 0
185 #define cErrReset 1
186
187 long cdecl (*Install) (WORD bus, tpTargetHandler Handler);
188 long cdecl (*Deinstall) (WORD bus, tpTargetHandler Handler);
189 long cdecl (*GetCmd) (WORD bus, BYTE *Cmd);
190 long cdecl (*SendData) (WORD bus, BYTE *Buffer, unsigned long Len);
191 long cdecl (*GetData) (WORD bus, void *Buffer, unsigned long Len);
192 long cdecl (*SendStatus) (WORD bus, UWORD Status);
193 long cdecl (*SendMsg) (WORD bus, UWORD Msg);
194 long cdecl (*GetMsg) (WORD bus, UWORD *Msg);
195
196 tReqData *ReqData;
197 } tScsiCall;
198
199 typedef tScsiCall *tpScsiCall;
200
201
202 LOCAL int num_handle_opened = 0;
203 LOCAL tHandle tab_handle_opened[MAX_SCSIDRV_HANDLE];
204 LOCAL SCSI *scgp_local;
205
206 tpScsiCall scsicall;
207
208 struct bus_struct {
209 tBusInfo bus;
210 tDevInfo *dev[MAX_TGT];
211 };
212
213 struct scg_local {
214 struct bus_struct *atari_bus[MAX_SCG];
215 };
216
217 #define scglocal(p) ((struct scg_local *)((p)->local))
218
219 /*
220 * Return version information for the low level SCSI transport code.
221 * This has been introduced to make it easier to trace down problems
222 * in applications.
223 */
224 LOCAL char *
scgo_version(scgp,what)225 scgo_version(scgp, what)
226 SCSI *scgp;
227 int what;
228 {
229 if (scgp != (SCSI *)0) {
230 switch (what) {
231
232 case SCG_VERSION:
233 return (_scg_trans_version);
234 /*
235 * If you changed this source, you are not allowed to
236 * return "schily" for the SCG_AUTHOR request.
237 */
238 case SCG_AUTHOR:
239 return (_scg_auth);
240 case SCG_SCCS_ID:
241 return (__sccsid);
242 }
243 }
244 return ((char *)0);
245 }
246
247
248
249 LOCAL int
scgo_help(scgp,f)250 scgo_help(scgp, f)
251 SCSI *scgp;
252 FILE *f;
253 {
254 __scg_help(f, "SCSIDRV Interface", "Atari generic SCSI implementation",
255 "", "bus,target,lun", "1,2,0", TRUE, FALSE);
256 printf("\nSCSIDRV driver is needed to enable libscg on Atari computers.\n");
257 printf("If you are using HDDRIVER, it already includes the SCSIDRV\n");
258 printf("programming interface otherwise you must run SCSIDRV.PRG before.\n");
259 printf("The following bus-numbers are reserved for this:\n");
260 printf("0 (ACSI)\n");
261 printf("1 (Standard SCSI: Falcon, TT, Medusa, MagicMac...)\n");
262 printf("2 (IDE in Atari-compatibles)\n");
263 printf("For further information, see packages SCSIDRV.ZIP and CBHD502.ZIP.\n");
264
265 return (0);
266 }
267
268
269 LOCAL void
scsidrv_close()270 scsidrv_close()
271 {
272 long rc;
273
274 rc = (long)scsicall->Close;
275 {
276 register long retvalue __asm__("d0");
277
278 /* BEGIN CSTYLED */
279 __asm__ volatile ("
280 movl %1,sp@-;
281 jbsr (%2);
282 lea sp@(4),sp "
283 : "=r"(retvalue) /* outputs */
284 : "r"((tHandle) scgp_local->fd),"a"(rc) /* inputs */
285 : "d0", "d1", "d2", "a0", "a1", "a2" /* clobbered regs */
286 AND_MEMORY);
287 /* END CSTYLED */
288 }
289
290 num_handle_opened = num_handle_opened - 1;
291 if ((num_handle_opened-1) >= 0)
292 scgp_local->fd = (int)tab_handle_opened[num_handle_opened-1];
293 else
294 scgp_local->fd = 0;
295 }
296
297 LOCAL void
atari_free_scsi_all()298 atari_free_scsi_all()
299 {
300 int i;
301 int j;
302
303 for (j = 0; j < MAX_SCG; j++) {
304 if (scglocal(scgp_local)->atari_bus[j] != (struct bus_struct *)-1) {
305 for (i = 0; i < MAX_TGT; i++) {
306 if (scglocal(scgp_local)->atari_bus[j]->dev[i] != (tDevInfo *)-1) {
307 free(scglocal(scgp_local)->atari_bus[j]->dev[i]);
308 }
309 }
310 free(scglocal(scgp_local)->atari_bus[j]);
311 }
312 }
313 if (scgp_local->local) {
314 free(scgp_local->local);
315 }
316
317 scgo_freebuf(scgp_local);
318 }
319
320
321
322 LOCAL int
scgo_open(scgp,device)323 scgo_open(scgp, device)
324 SCSI *scgp;
325 char *device;
326
327 {
328 /* SCSIDRV present ? */
329 BOOL scsidrv = FALSE;
330 BOOL nopen = FALSE;
331 void *oldstack;
332 long rc_bus;
333 int i;
334 int j;
335 tBusInfo Bus;
336 WORD Inq_bus = cInqFirst;
337 long cookie_value;
338
339 scsicall = NULL;
340 scgp_local = scgp;
341
342 if (Getcookie(0x53435349L, &cookie_value) == 0) {
343 scsicall = (tpScsiCall)cookie_value;
344 printf("SCSIDRV found on your ATARI!\n");
345 scsidrv = TRUE;
346 } else {
347 printf("I can't find SCSIDRV on your ATARI...\n");
348 scsidrv = FALSE;
349 nopen = FALSE;
350 }
351
352
353 if (scsidrv == TRUE) {
354 if (scgp->local == NULL) {
355 scgp->local = malloc(sizeof (struct scg_local));
356 if (scgp->local == NULL)
357 return (0);
358 for (j = 0; j < MAX_SCG; j++) {
359 scglocal(scgp)->atari_bus[j] = (struct bus_struct *)-1;
360 }
361 }
362
363
364
365 oldstack = (void *)Super(NULL);
366 rc_bus = (long)scsicall->InquireSCSI; /* busses available */
367 /*
368 * InquireSCSI
369 */
370 {
371 register long ret_bus_value __asm__("d0") = 0; /* Return of InquireSCSI */
372 long ret_bus = 0;
373
374 while (ret_bus == 0) {
375
376 /* BEGIN CSTYLED */
377 __asm__ volatile ("
378 movl %1,sp@-; /* Pointer of bus structure (32-bit long)*/
379 movw %3,sp@-; /* Inq_bus argument (16-bit WORD) */
380 jbsr (%2); /* Call to InquireSCSI SCSIDRV function */
381 lea sp@(6),sp /* Fix the stack */ "
382 : "=r"(ret_bus_value) /* outputs */
383 : "r"(&Bus),"a"(rc_bus), "r"(Inq_bus) /* inputs */
384 : "d0", "d1", "d2", "a0", "a1", "a2" /* clobbered regs */
385 AND_MEMORY);
386 /* END CSTYLED */
387
388 ret_bus = ret_bus_value;
389 if (ret_bus == 0) {
390 scglocal(scgp)->atari_bus[Bus.BusNo] = malloc(sizeof (struct bus_struct));
391 memcpy(&scglocal(scgp)->atari_bus[Bus.BusNo]->bus, &Bus, sizeof (tBusInfo));
392 for (i = 0; i < MAX_TGT; i++) {
393 scglocal(scgp)->atari_bus[Bus.BusNo]->dev[i] = (tDevInfo *)-1;
394 }
395
396 {
397 long rc_dev;
398 WORD Inq_dev = cInqFirst;
399 register long ret_dev_value __asm__("d0") = 0;
400 long ret_dev = 0;
401 tDevInfo Dev;
402 rc_dev = (long)scsicall->InquireBus; /* we inquiry for devices in bus Bus.BusNo */
403 while (ret_dev == 0) {
404
405 /* BEGIN CSTYLED */
406 __asm__ volatile ("
407 movl %2,sp@-;
408 movw %1,sp@-;
409 movw %4,sp@-;
410 jbsr (%3);
411 lea sp@(8),sp "
412 : "=r"(ret_dev_value) /* outputs */
413 : "r"(Bus.BusNo),"r"(&Dev),"a"(rc_dev), "r"(Inq_dev) /* inputs */
414 : "d0", "d1", "d2", "a0", "a1", "a2" /* clobbered regs */
415 AND_MEMORY);
416 /* END CSTYLED */
417
418 ret_dev = ret_dev_value;
419 if (ret_dev == 0) {
420 scglocal(scgp)->atari_bus[Bus.BusNo]->dev[(int)Dev.SCSIId.lo] = malloc(sizeof (tDevInfo));
421 memcpy(scglocal(scgp)->atari_bus[Bus.BusNo]->dev[(int)Dev.SCSIId.lo], &Dev, sizeof (tDevInfo));
422 }
423 Inq_dev = cInqNext;
424 }
425 }
426
427 }
428 Inq_bus = cInqNext;
429 }
430 }
431
432
433 Super(oldstack);
434
435 atexit(scsidrv_close);
436 atexit(atari_free_scsi_all);
437
438 nopen = TRUE;
439 }
440 return (nopen);
441
442 }
443
444
445
446 LOCAL int
scgo_close(SCSI * scgp)447 scgo_close(SCSI * scgp)
448 {
449 scsidrv_close();
450 atari_free_scsi_all();
451 return (0);
452 }
453
454
455 LOCAL long
scgo_maxdma(scgp,amt)456 scgo_maxdma(scgp, amt)
457 SCSI *scgp;
458 long amt;
459 {
460 /* return (63*1024); */
461 return (256*1024);
462 }
463
464
465
466 LOCAL void *
scgo_getbuf(scgp,amt)467 scgo_getbuf(scgp, amt)
468 SCSI *scgp;
469 long amt;
470 {
471 if (scgp->debug > 0) {
472 js_fprintf((FILE *)scgp->errfile,
473 "scgo_getbuf: %ld bytes\n", amt);
474 }
475 scgp->bufbase = malloc((size_t)(amt));
476 return (scgp->bufbase);
477
478 }
479
480
481
482 LOCAL void
scgo_freebuf(scgp)483 scgo_freebuf(scgp)
484 SCSI *scgp;
485 {
486 if (scgp->bufbase)
487 free(scgp->bufbase);
488 scgp->bufbase = NULL;
489 }
490
491
492
493
494 LOCAL int
scgo_numbus(scgp)495 scgo_numbus(scgp)
496 SCSI *scgp;
497 {
498 return (MAX_SCG);
499 }
500
501
502
503 LOCAL BOOL
scgo_havebus(scgp,busno)504 scgo_havebus(scgp, busno)
505 SCSI *scgp;
506 int busno;
507 {
508 return (TRUE);
509 }
510
511
512
513 LOCAL int
scgo_fileno(scgp,busno,tgt,tlun)514 scgo_fileno(scgp, busno, tgt, tlun)
515 SCSI *scgp;
516 int busno;
517 int tgt;
518 int tlun;
519 {
520 long rc;
521 unsigned long MaxLen;
522 int fd = 0;
523 tBusInfo Bus;
524 void *oldstack;
525
526 if (scgp_local->fd > 0) { /* handle exists ? */
527 scsidrv_close();
528 }
529
530 if (busno < 0 || busno >= MAX_SCG ||
531 tgt < 0 || tgt >= MAX_TGT ||
532 tlun < 0 || tlun >= MAX_LUN) {
533 errno = EINVAL;
534 return (-1);
535 }
536
537 if (scglocal(scgp)->atari_bus[busno] == (struct bus_struct *)-1) {
538 errno = EINVAL;
539 return (-1);
540 }
541
542 if ((struct tDevInfo *) scglocal(scgp)->atari_bus[busno]->dev[tgt] == (struct tDevInfo *)-1) {
543 errno = EINVAL;
544 return (-1);
545 }
546
547
548 oldstack = (void *)Super(NULL);
549 rc = (long)scsicall->Open;
550 {
551 register long retvalue __asm__("d0") = 0;
552
553 /* BEGIN CSTYLED */
554 __asm__ volatile ("
555 movl %3,sp@-;
556 movl %2,sp@-;
557 movw %1,sp@-;
558 jbsr (%4);
559 lea sp@(10),sp "
560 : "=r"(retvalue) /* outputs */
561 : "r"(scglocal(scgp)->atari_bus[busno]->bus.BusNo),
562 "r"(&scglocal(scgp)->atari_bus[busno]->dev[tgt]->SCSIId),"r"(&MaxLen),"a"(rc) /* inputs */
563 : "d0", "d1", "d2", "a0", "a1", "a2" /* clobbered regs */
564 AND_MEMORY);
565 /* END CSTYLED */
566
567 fd = (int)retvalue;
568 }
569
570
571 Super(oldstack);
572
573 if (fd > 0) {
574 tab_handle_opened[num_handle_opened] = (tHandle)fd;
575 num_handle_opened = num_handle_opened + 1;
576 return (fd);
577 } else {
578 return (-1);
579 }
580 }
581
582
583 LOCAL int
scgo_initiator_id(scgp)584 scgo_initiator_id(scgp)
585 SCSI *scgp;
586 {
587 return (-1);
588 }
589
590
591 LOCAL int
scgo_isatapi(scgp)592 scgo_isatapi(scgp)
593 SCSI *scgp;
594 {
595 return (FALSE);
596 }
597
598
599
600 LOCAL int
scgo_reset(scgp,what)601 scgo_reset(scgp, what)
602 SCSI *scgp;
603 int what;
604 {
605 /* XXX synchronous reset command - is this wise? */
606 errno = EINVAL;
607 return (-1);
608 }
609
610
611 LOCAL int
scgo_send(scgp)612 scgo_send(scgp)
613 SCSI *scgp;
614 {
615 long rc;
616 void *oldstack;
617 tSCSICmd cmd;
618 tBusInfo Bus;
619 tDevInfo Dev;
620 unsigned long MaxLen;
621 long ret = 0;
622 BYTE reqbuff[18];
623
624 scgp->scmd->ux_errno = 0;
625
626 if (scgp->fd <= 0) {
627 scgp->scmd->error = SCG_FATAL;
628 return (0);
629 }
630
631
632 oldstack = (void *)Super(NULL);
633 cmd.Handle = (tHandle) scgp->fd;
634 cmd.Cmd = malloc(scgp->scmd->cdb_len);
635 movebytes(&scgp->scmd->cdb, cmd.Cmd, scgp->scmd->cdb_len);
636 cmd.CmdLen = /* (UWORD) */ scgp->scmd->cdb_len;
637 cmd.Buffer = scgp->scmd->addr;
638 cmd.TransferLen = scgp->scmd->size;
639 cmd.SenseBuffer = scgp->scmd->u_sense.cmd_sense;
640 fillbytes(cmd.SenseBuffer, sizeof (reqbuff), '\0');
641 cmd.Timeout = scgp->scmd->timeout * 200;
642 cmd.Flags = scgp->scmd->flags & SCG_RECV_DATA;
643 scgp->scmd->u_scb.cmd_scb[0] = 0;
644
645
646 if ((scgp->scmd->flags & SCG_RECV_DATA)) {
647 rc = (long)scsicall->In;
648 {
649 register long retvalue __asm__("d0");
650
651 /* BEGIN CSTYLED */
652 __asm__ volatile ("
653 movl %1,sp@-;
654 jbsr (%2);
655 lea sp@(4),sp "
656 : "=r"(retvalue) /* outputs */
657 : "r"(&cmd),"a"(rc) /* inputs */
658 : "d0", "d1", "d2", "a0", "a1", "a2" /* clobbered regs */
659 AND_MEMORY);
660 /* END CSTYLED */
661
662 ret = retvalue;
663 }
664 } else if (scgp->scmd->size > 0) {
665
666 rc = (long)scsicall->Out;
667 {
668 register long retvalue __asm__("d0");
669
670 /* BEGIN CSTYLED */
671 __asm__ volatile ("
672 movl %1,sp@-;
673 jbsr (%2);
674 lea sp@(4),sp "
675 : "=r"(retvalue) /* outputs */
676 : "r"(&cmd),"a"(rc) /* inputs */
677 : "d0", "d1", "d2", "a0", "a1", "a2" /* clobbered regs */
678 AND_MEMORY);
679 /* END CSTYLED */
680
681 ret = retvalue;
682 }
683 } else {
684
685 rc = (long)scsicall->Out;
686 {
687 register long retvalue __asm__("d0");
688
689 /* BEGIN CSTYLED */
690 __asm__ volatile ("
691 movl %1,sp@-;
692 jbsr (%2);
693 lea sp@(4),sp "
694 : "=r"(retvalue) /* outputs */
695 : "r"(&cmd),"a"(rc) /* inputs */
696 : "d0", "d1", "d2", "a0", "a1", "a2" /* clobbered regs */
697 AND_MEMORY);
698 /* BEGIN CSTYLED */
699
700 ret = retvalue;
701 }
702 }
703
704 Super(oldstack);
705
706 scgp->scmd->resid = 0;
707
708 scgp->scmd->sense_count = sizeof (reqbuff); /* 18 */
709 movebytes(cmd.SenseBuffer, &scgp->scmd->u_sense.cmd_sense, sizeof (reqbuff));
710
711 free(cmd.Cmd);
712
713 scgp->scmd->u_scb.cmd_scb[0] = ret;
714
715
716 switch (ret) {
717 case CHECKCONDITION:
718 scgp->scmd->ux_errno = geterrno();
719 scgp->scmd->error = SCG_NO_ERROR;
720 break;
721 case TIMEOUTERROR:
722 scgp->scmd->ux_errno = geterrno();
723 scgp->scmd->error = SCG_TIMEOUT;
724 break;
725 default:
726 if (ret < 0)
727 {
728 scgp->scmd->ux_errno = geterrno();
729 scgp->scmd->error = SCG_FATAL;
730 }
731 else
732 scgp->scmd->error = SCG_NO_ERROR;
733 break;
734 }
735
736 return (ret);
737 }
738