1 /* @(#)scsi-amigaos.c 1.8 06/11/26 Copyright 1997,2000-2003 J. Schilling */
2 #ifndef lint
3 static char __sccsid[] =
4 "@(#)scsi-amigaos.c 1.8 06/11/26 Copyright 1997,2000-2003 J. Schilling";
5 #endif
6 /*
7 * Interface for the AmigaOS generic SCSI implementation.
8 *
9 * Warning: you may change this source, but if you do that
10 * you need to change the _scg_version and _scg_auth* string below.
11 * You may not return "schily" for an SCG_AUTHOR request anymore.
12 * Choose your name instead of "schily" and make clear that the version
13 * string is related to a modified source.
14 *
15 * Copyright (c) 1997, 2000-2003 J. Schilling
16 * AmigaOS support code written by T. Langer
17 */
18 /*
19 * The contents of this file are subject to the terms of the
20 * Common Development and Distribution License, Version 1.0 only
21 * (the "License"). You may not use this file except in compliance
22 * with the License.
23 *
24 * See the file CDDL.Schily.txt in this distribution for details.
25 * A copy of the CDDL is also available via the Internet at
26 * http://www.opensource.org/licenses/cddl1.txt
27 *
28 * The following exceptions apply:
29 * CDDL �3.6 needs to be replaced by: "You may create a Larger Work by
30 * combining Covered Software with other code if all other code is governed by
31 * the terms of a license that is OSI approved (see www.opensource.org) and
32 * you may distribute the Larger Work as a single product. In such a case,
33 * You must make sure the requirements of this License are fulfilled for
34 * the Covered Software."
35 *
36 * When distributing Covered Code, include this CDDL HEADER in each
37 * file and include the License file CDDL.Schily.txt from this distribution.
38 */
39
40 #define BOOL int
41
42 #include <schily/strdefs.h>
43 #include <exec/ports.h>
44 #include <exec/io.h>
45 #include <exec/errors.h>
46 #include <devices/scsidisk.h>
47 #include <devices/timer.h>
48 #include <exec/semaphores.h>
49 #include <exec/memory.h>
50 #include <exec/execbase.h>
51 #include <clib/exec_protos.h>
52 #include <clib/alib_protos.h>
53
54 /*
55 * Warning: you may change this source, but if you do that
56 * you need to change the _scg_version and _scg_auth* string below.
57 * You may not return "schily" for an SCG_AUTHOR request anymore.
58 * Choose your name instead of "schily" and make clear that the version
59 * string is related to a modified source.
60 */
61 LOCAL char _scg_trans_version[] = "scsi-amigaos.c-1.8"; /* The version for this transport */
62 LOCAL char _scg_auth[] = "T. Langer";
63
64 #define MAX_SCG 8 /* Max # of SCSI controllers */
65 #define MAX_TGT 8
66 #define MAX_LUN 8
67 #define MAX_DEV MAX_SCG*MAX_TGT*MAX_LUN
68
69 struct scg_local {
70 int scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
71 };
72
73 #define scglocal(p) ((struct scg_local *)((p)->local))
74
75 #define MAX_DMA_AMIGAOS (64*1024)
76
77 LOCAL struct IOReq {
78 struct IOStdReq *ioReq;
79 int ref_count;
80 } request[MAX_DEV];
81
82 LOCAL char *devs[MAX_SCG];
83 LOCAL struct MsgPort *ioMsgPort = NULL;
84 LOCAL struct timerequest *timer_io = NULL;
85 LOCAL struct MsgPort *timerMsgPort = NULL;
86 LOCAL int initialized = 0;
87 LOCAL int last_bus = -1;
88 /* my private var: for debug purpose only */
89 LOCAL int ami_debug = 0;
90
91 extern struct ExecBase *SysBase;
92 #define IOERR_TIMEOUT (-8)
93 #define CHECK_CONDITION 0x02
94 #define DUNIT(b, t, l) (100 * b) + (10 * (l < 0 ? 0:l)) + t
95
96 LOCAL void amiga_init __PR((void));
97 LOCAL int amiga_open_scsi __PR((int bus, int tgt, int lun, SCSI *scgp));
98 LOCAL void amiga_close_scsi __PR((int fd));
99 LOCAL void amiga_close_scsi_all __PR((void));
100 LOCAL void amiga_scan_devices __PR((void));
101 LOCAL int amiga_find_device __PR((char *device));
102 LOCAL int amiga_open_timer __PR((void));
103 LOCAL void amiga_close_timer __PR((void));
104 LOCAL int amiga_get_scsi_bus __PR((char *device));
105
106 /*
107 * Return version information for the low level SCSI transport code.
108 * This has been introduced to make it easier to trace down problems
109 * in applications.
110 */
111 LOCAL char *
scgo_version(scgp,what)112 scgo_version(scgp, what)
113 SCSI *scgp;
114 int what;
115 {
116 if (scgp != (SCSI *)0) {
117 switch (what) {
118
119 case SCG_VERSION:
120 return (_scg_trans_version);
121 /*
122 * If you changed this source, you are not allowed to
123 * return "schily" for the SCG_AUTHOR request.
124 */
125 case SCG_AUTHOR:
126 /* return (_scg_auth_schily);*/
127 return (_scg_auth);
128 case SCG_SCCS_ID:
129 return (__sccsid);
130 }
131 }
132 return ((char *)0);
133 }
134
135 LOCAL int
scgo_help(scgp,f)136 scgo_help(scgp, f)
137 SCSI *scgp;
138 FILE *f;
139 {
140 __scg_help(f, "Amiga SCSI", "Generic SCSI",
141 "", "bus,target,lun or xxx.device:b,t,l", "1,2,0 or scsi.device:1,2,0", TRUE, FALSE);
142 return (0);
143 }
144
145 LOCAL int
scgo_open(scgp,device)146 scgo_open(scgp, device)
147 SCSI *scgp;
148 char *device;
149 {
150 int busno = scg_scsibus(scgp);
151 int tgt = scg_target(scgp);
152 int tlun = scg_lun(scgp);
153 register int f;
154 register int b;
155 register int t;
156 register int l;
157 register int nopen = 0;
158
159 if (initialized == 0) {
160 amiga_init();
161 initialized = 1;
162 }
163
164 if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
165 errno = EINVAL;
166 if (scgp->errstr) {
167 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
168 "Illegal value for busno, target or lun '%d,%d,%d'",
169 busno, tgt, tlun);
170 }
171 return (-1);
172 }
173 if (scgp->local == NULL) {
174 scgp->local = malloc(sizeof (struct scg_local));
175 if (scgp->local == NULL)
176 return (0);
177
178 for (b = 0; b < MAX_SCG; b++) {
179 for (t = 0; t < MAX_TGT; t++) {
180 for (l = 0; l < MAX_LUN; l++) {
181 scglocal(scgp)->scgfiles[b][t][l] = -1;
182 }
183 }
184 }
185 }
186
187 if (device == NULL || *device == '\0') {
188
189 if (last_bus == -1) {
190 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
191 "No scsi device found");
192 return (-1);
193 }
194 if (busno < 0 && tgt < 0 && tlun < 0) {
195 /* cdrecord -scanbus */
196 for (b = 0; b <= last_bus; b++) {
197 for (t = 0; t < MAX_TGT; t++) {
198 for (l = 0; l < MAX_LUN; l++) {
199 f = amiga_open_scsi(b, t, l, scgp);
200 if (f != -1) {
201 scglocal(scgp)->scgfiles[b][t][l] = f;
202 nopen++;
203 }
204 }
205 }
206 }
207 } else {
208 /* cdrecord [-scanbus] dev=b,t,l */
209 f = amiga_open_scsi(busno, tgt, tlun, scgp);
210 if (f != -1) {
211 scglocal(scgp)->scgfiles[busno][tgt][tlun] = f;
212 nopen++;
213 }
214 }
215 } else {
216 if (busno < 0 && tgt < 0 && tlun < 0) {
217 /* cdrecord -scanbus dev=xxx.device */
218 b = amiga_get_scsi_bus(device);
219 if (b != -1) {
220 for (t = 0; t < MAX_TGT; t++) {
221 for (l = 0; l < MAX_LUN; l++) {
222 f = amiga_open_scsi(b, t, l, scgp);
223 if (f != -1) {
224 scglocal(scgp)->scgfiles[b][t][l] = f;
225 nopen++;
226 }
227 }
228 }
229 } else {
230 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
231 "Scsi device %s not found", device);
232 }
233 } else {
234 /* cdrecord [-scanbus] dev=xxx.device:b,t,l */
235 /*
236 * this is a special case, in which the scsi device is accessed just by
237 * name, bus parameter from the command is ignored.
238 */
239 b = amiga_get_scsi_bus(device);
240 if (b != -1) {
241 f = amiga_open_scsi(b, tgt, tlun, scgp);
242 if (f != -1) {
243 scglocal(scgp)->scgfiles[busno][tgt][tlun] = f;
244 nopen++;
245 }
246 } else {
247 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
248 "Scsi device %s not found", device);
249 }
250 }
251 }
252
253 return (nopen);
254 }
255
256 LOCAL int
scgo_close(scgp)257 scgo_close(scgp)
258 SCSI *scgp;
259 {
260 register int b;
261 register int t;
262 register int l;
263
264 if (scgp->local == NULL)
265 return (-1);
266
267 for (b = 0; b < MAX_SCG; b++) {
268 for (t = 0; t < MAX_TGT; t++) {
269 for (l = 0; l < MAX_LUN; l++) {
270 if (scglocal(scgp)->scgfiles[b][t][l] >= 0)
271 amiga_close_scsi(scglocal(scgp)->scgfiles[b][t][l]);
272 scglocal(scgp)->scgfiles[b][t][l] = -1;
273 }
274 }
275 }
276 return (0);
277 }
278
279 LOCAL long
scgo_maxdma(scgp,amt)280 scgo_maxdma(scgp, amt)
281 SCSI *scgp;
282 long amt;
283 {
284 return (MAX_DMA_AMIGAOS);
285 }
286
287 LOCAL void *
scgo_getbuf(scgp,amt)288 scgo_getbuf(scgp, amt)
289 SCSI *scgp;
290 long amt;
291 {
292 if (scgp->debug > 0) {
293 js_fprintf((FILE *)scgp->errfile,
294 "scgo_getbuf: %ld bytes\n", amt);
295 }
296 scgp->bufbase = valloc((size_t)(amt));
297 return (scgp->bufbase);
298 }
299
300 LOCAL void
scgo_freebuf(scgp)301 scgo_freebuf(scgp)
302 SCSI *scgp;
303 {
304 if (scgp->bufbase)
305 free(scgp->bufbase);
306 scgp->bufbase = NULL;
307 }
308
309 LOCAL int
scgo_numbus(scgp)310 scgo_numbus(scgp)
311 SCSI *scgp;
312 {
313 return (MAX_SCG);
314 }
315
316 LOCAL BOOL
scgo_havebus(scgp,busno)317 scgo_havebus(scgp, busno)
318 SCSI *scgp;
319 int busno;
320 {
321 register int t;
322 register int l;
323
324 if (busno < 0 || busno >= MAX_SCG)
325 return (FALSE);
326
327 if (scgp->local == NULL)
328 return (FALSE);
329
330 for (t = 0; t < MAX_TGT; t++) {
331 for (l = 0; l < MAX_LUN; l++)
332 if (scglocal(scgp)->scgfiles[busno][t][l] != -1)
333 return (TRUE);
334 }
335 return (FALSE);
336 }
337
338 LOCAL int
scgo_fileno(scgp,busno,tgt,tlun)339 scgo_fileno(scgp, busno, tgt, tlun)
340 SCSI *scgp;
341 int busno;
342 int tgt;
343 int tlun;
344 {
345 if (busno < 0 || busno >= MAX_SCG ||
346 tgt < 0 || tgt >= MAX_TGT ||
347 tlun < 0 || tlun >= MAX_LUN)
348 return (-1);
349
350 if (scgp->local == NULL)
351 return (-1);
352
353 return ((int)scglocal(scgp)->scgfiles[busno][tgt][tlun]);
354 }
355
356 LOCAL int
scgo_initiator_id(scgp)357 scgo_initiator_id(scgp)
358 SCSI *scgp;
359 {
360 return (-1);
361 }
362
363 LOCAL int
scgo_isatapi(scgp)364 scgo_isatapi(scgp)
365 SCSI *scgp;
366 {
367 return (FALSE);
368 }
369
370 LOCAL int
scgo_reset(scgp,what)371 scgo_reset(scgp, what)
372 SCSI *scgp;
373 int what;
374 {
375 /* XXX Is there really no reset function on AmigaOS? */
376 errno = EINVAL;
377 return (-1);
378 }
379
380 LOCAL int
scgo_send(scgp)381 scgo_send(scgp)
382 SCSI *scgp;
383 {
384 register struct IOStdReq *ioreq = NULL;
385 struct SCSICmd Cmd;
386 int ret = 0;
387 struct scg_cmd *sp = scgp->scmd;
388
389 sp->error = SCG_NO_ERROR;
390 sp->sense_count = 0;
391 sp->u_scb.cmd_scb[0] = 0;
392 sp->resid = 0;
393
394 if (scgp->fd < 0) {
395 sp->error = SCG_FATAL;
396 return (0);
397 }
398 ioreq = request[scgp->fd].ioReq;
399 if (ioreq == NULL) {
400 sp->error = SCG_FATAL;
401 return (0);
402 }
403 ioreq->io_Length = sizeof (struct SCSICmd);
404 ioreq->io_Data = &Cmd;
405 ioreq->io_Command = HD_SCSICMD;
406
407 Cmd.scsi_Flags = SCSIF_AUTOSENSE; /* We set the SCSI cmd len */
408 if (sp->flags & SCG_RECV_DATA)
409 Cmd.scsi_Flags |= SCSIF_READ;
410 else if (sp->size > 0)
411 Cmd.scsi_Flags |= SCSIF_WRITE;
412
413 Cmd.scsi_Command = sp->cdb.cmd_cdb;
414 Cmd.scsi_CmdLength = sp->cdb_len;
415 Cmd.scsi_Data = (UWORD *) sp->addr;
416 Cmd.scsi_Length = sp->size;
417 Cmd.scsi_Actual = 0;
418
419 Cmd.scsi_SenseData = sp->u_sense.cmd_sense;
420 Cmd.scsi_SenseLength = sp->sense_len;
421 Cmd.scsi_SenseActual = 0;
422 Cmd.scsi_Status = 0;
423
424 do_scsi_cmd(ioreq, sp->timeout);
425
426 fillbytes(&sp->scb, sizeof (sp->scb), '\0');
427 sp->resid = Cmd.scsi_Length - Cmd.scsi_Actual;
428
429 if (sp->resid < 0)
430 sp->resid = 0;
431 sp->sense_count = Cmd.scsi_SenseActual;
432 if (sp->sense_count < 0)
433 sp->sense_count;
434
435 if (sp->sense_count > SCG_MAX_SENSE)
436 sp->sense_count = SCG_MAX_SENSE;
437 sp->u_scb.cmd_scb[0] = Cmd.scsi_Status;
438
439 if (ioreq->io_Error)
440 sp->ux_errno = EIO;
441
442 if (ami_debug)
443 printf("ioreq->io_Error: %ld; status %ld\n", ioreq->io_Error, Cmd.scsi_Status);
444
445 switch (ioreq->io_Error) {
446 case 0:
447 sp->error = SCG_NO_ERROR;
448 break;
449 case IOERR_TIMEOUT:
450 sp->error = SCG_TIMEOUT;
451 break;
452 case HFERR_DMA:
453 case IOERR_UNITBUSY:
454 case HFERR_Phase:
455 case HFERR_Parity:
456 case HFERR_BadStatus:
457 if (Cmd.scsi_Status == CHECK_CONDITION) {
458 sp->error = SCG_NO_ERROR;
459 } else {
460 sp->error = SCG_RETRYABLE;
461 }
462 break;
463 default:
464 /* XXX was kann sonst noch passieren? */
465 sp->error = SCG_FATAL;
466 break;
467 }
468
469 return (ret);
470 }
471
472 LOCAL int
do_scsi_cmd(scsi_io,timeout)473 do_scsi_cmd(scsi_io, timeout)
474 struct IOStdReq *scsi_io;
475 int timeout;
476 {
477 ULONG scsi_flag = 0;
478 ULONG timer_flag = 0;
479 ULONG wait_sigs = 0;
480 ULONG wait_ret = 0;
481 int ret = 0;
482
483 scsi_flag = 1L<<scsi_io->io_Message.mn_ReplyPort->mp_SigBit;
484 wait_sigs = scsi_flag;
485
486 SetSignal(0L, scsi_flag);
487 SendIO((struct IORequest *)scsi_io);
488 if (timer_io) {
489 timer_flag = 1L<<timerMsgPort->mp_SigBit;
490 wait_sigs |= timer_flag;
491 timer_io->tr_time.tv_secs = timeout;
492 SetSignal(0L, timer_flag);
493 SendIO((struct IORequest *)timer_io);
494 }
495
496 wait_ret = Wait(wait_sigs);
497
498 if (wait_ret & scsi_flag) {
499 WaitIO((struct IORequest *)scsi_io);
500 if (timer_io) {
501 if (!CheckIO((struct IORequest *) timer_io)) {
502 AbortIO((struct IORequest *)timer_io);
503 WaitIO((struct IORequest *)timer_io);
504 }
505 }
506 } else if (wait_ret & timer_flag) {
507 WaitIO((struct IORequest *)timer_io);
508 if (!CheckIO((struct IORequest *) scsi_io)) {
509 AbortIO((struct IORequest *)scsi_io);
510 if (scsi_io->io_Error == IOERR_ABORTED) {
511 WaitIO((struct IORequest *)scsi_io);
512 }
513 }
514 scsi_io->io_Error = IOERR_TIMEOUT;
515 }
516
517 return (scsi_io->io_Error);
518 }
519
520 /*--------------------------------------------------------------------------*/
521
522 /* strlwr: seems not to be implemented in ixemul */
523 LOCAL char *
strlwr(s)524 strlwr(s)
525 char *s;
526 {
527 unsigned char *s1;
528
529 s1 = (unsigned char *)s;
530 while (*s1) {
531 if ((*s1 > ('A'-1)) && (*s1 < ('Z'+1)))
532 *s1 += 'a'-'A';
533 s1++;
534 }
535 return (s);
536 }
537
538 /*
539 * amiga specific functions
540 */
541 LOCAL void
amiga_init()542 amiga_init()
543 {
544 memset(request, 0, sizeof (request));
545 amiga_scan_devices();
546 if (ami_debug)
547 printf("scanning bus. %ld device(s) found\n", last_bus + 1);
548
549 atexit(amiga_close_scsi_all);
550 }
551
552 LOCAL void
amiga_scan_devices()553 amiga_scan_devices()
554 {
555 /*
556 * searching all known scsi devices
557 * for first there is only a (full) support for scsi.device and amithlon.device.
558 * This are devices i tested.
559 * All the other devices have to be specified by name (i.e. cdrecord dev=blabla.device:0,0,0)
560 * but didn't appear in the scanbus list. Later they should/may be also added to the
561 * main_dev_list (after testing).
562 */
563 const char *main_dev_list[] = { "scsi.device", "amithlon.device", NULL };
564
565 int i;
566 char **main_dev;
567
568 main_dev = (char **)main_dev_list;
569 while (*main_dev) {
570 if (last_bus == MAX_SCG - 1)
571 break;
572 if (amiga_find_device(*main_dev)) {
573 last_bus++;
574 devs[last_bus] = strdup(*main_dev);
575 for (i = 2; i < MAX_SCG; i++) {
576 char tmp[256];
577 if (last_bus == MAX_SCG - 1)
578 break;
579 if (i == 2) {
580 sprintf(tmp, "2nd.%s", *main_dev);
581 } else if (i == 3) {
582 sprintf(tmp, "3rd.%s", *main_dev);
583 } else {
584 sprintf(tmp, "%ldth.%s", i, *main_dev);
585 }
586 if (amiga_find_device(tmp)) {
587 last_bus++;
588 devs[last_bus] = strdup(tmp);
589 } else {
590 break;
591 }
592 }
593 }
594 main_dev++;
595 }
596 }
597
598 LOCAL void
amiga_close_scsi(fd)599 amiga_close_scsi(fd)
600 int fd;
601 {
602 if (request[fd].ref_count > 0) {
603 request[fd].ref_count--;
604 if (request[fd].ref_count == 0) {
605 CloseDevice((struct IORequest *) request[fd].ioReq);
606 DeleteStdIO(request[fd].ioReq);
607 request[fd].ioReq = NULL;
608 if (ami_debug) {
609 printf("closing device fd %ld\n", fd);
610 }
611 }
612 }
613 }
614
615 LOCAL void
amiga_close_scsi_all()616 amiga_close_scsi_all()
617 {
618 int i;
619
620 for (i = 0; i < MAX_DEV; i++) {
621 if (request[i].ioReq != NULL) {
622 if (ami_debug) {
623 printf("closing device fd %ld\n", i);
624 }
625 CloseDevice((struct IORequest *) request[i].ioReq);
626 DeleteStdIO(request[i].ioReq);
627 request[i].ioReq = NULL;
628 }
629 }
630
631 if (ioMsgPort) {
632 DeletePort(ioMsgPort);
633 ioMsgPort = NULL;
634 }
635 amiga_close_timer();
636
637 for (i = 0; i < MAX_SCG; i++) {
638 free(devs[i]);
639 }
640 }
641
642 LOCAL int
amiga_open_scsi(bus,tgt,lun,scgp)643 amiga_open_scsi(bus, tgt, lun, scgp)
644 int bus;
645 int tgt;
646 int lun;
647 SCSI *scgp;
648 {
649 int fd = bus * MAX_TGT * MAX_LUN + tgt * MAX_LUN + lun;
650 int unit = DUNIT(bus, tgt, lun);
651 char *dev = devs[bus];
652
653 if (dev == NULL) {
654 if (scgp->errstr) {
655 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
656 "No scsi device found at bus %ld\n", bus);
657 }
658 return (-1);
659 }
660
661 if (ioMsgPort == NULL) {
662 ioMsgPort = CreatePort(NULL, 0);
663 }
664
665 if (ioMsgPort != NULL) {
666 if (request[fd].ioReq == NULL) {
667 request[fd].ioReq = CreateStdIO(ioMsgPort);
668 }
669
670 if (request[fd].ioReq != NULL) {
671 if (ami_debug)
672 printf("trying %s, unit %ld\n", dev, unit);
673 if (OpenDevice(dev, unit, (struct IORequest *)request[fd].ioReq, 0L)) {
674 if (scgp->errstr) {
675 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
676 "Cannot open %s\n", dev);
677 }
678 if (request[fd].ref_count == 0) {
679 DeleteStdIO(request[fd].ioReq);
680 request[fd].ioReq = NULL;
681 }
682 fd = -1;
683 } else {
684 request[fd].ref_count++;
685 if (ami_debug)
686 printf("opening %s, unit %ld as fd %ld count %ld\n", dev, unit, fd, request[fd].ref_count);
687 }
688 } else {
689 if (scgp->errstr) {
690 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
691 "Cannot create IOReq");
692 }
693 }
694 } else {
695 if (scgp->errstr) {
696 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
697 "Cannot open Message Port");
698 }
699 }
700
701 return (fd);
702 }
703
704 LOCAL int
amiga_open_timer()705 amiga_open_timer()
706 {
707 int ret = 0;
708
709 /* we need the timer to catch scsi timeouts */
710 if (timer_io == NULL) {
711 if (ami_debug)
712 printf("opening timer\n");
713
714 timerMsgPort = CreatePort(NULL, 0);
715 if (timerMsgPort) {
716 timer_io = (struct timerequest *)CreateExtIO(timerMsgPort, sizeof (struct timerequest));
717 if (timer_io) {
718 if (OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest *)timer_io, 0)) {
719 printf("Warning: can't open timer device\n");
720 DeleteExtIO((struct IORequest *) timer_io);
721 DeletePort(timerMsgPort);
722 timer_io = NULL;
723 timerMsgPort = NULL;
724 ret = 1;
725 } else {
726 timer_io->tr_node.io_Command = TR_ADDREQUEST;
727 timer_io->tr_time.tv_micro = 0;
728 }
729 } else {
730 printf("Warning: can't create timer request\n");
731 DeletePort(timerMsgPort);
732 timerMsgPort = NULL;
733 ret = 1;
734 }
735 } else {
736 printf("Warning: can't create timer port\n");
737 ret = 1;
738 }
739 }
740 return (ret);
741 }
742
743 LOCAL void
amiga_close_timer()744 amiga_close_timer()
745 {
746 if (timer_io) {
747 if (ami_debug)
748 printf("closing timer\n");
749
750 AbortIO((struct IORequest *) timer_io);
751 WaitIO((struct IORequest *) timer_io);
752 CloseDevice((struct IORequest *)timer_io);
753 DeleteExtIO((struct IORequest *) timer_io);
754 DeletePort(timerMsgPort);
755 timer_io = NULL;
756 timerMsgPort = NULL;
757 }
758 }
759
760 LOCAL int
amiga_get_scsi_bus(device)761 amiga_get_scsi_bus(device)
762 char *device;
763 {
764 int i;
765 char *tmp = strdup(device);
766
767 strlwr(tmp);
768 for (i = 0; i <= last_bus; i++) {
769 if (strcmp(devs[i], tmp) == 0) {
770 return (i);
771 }
772 }
773
774 if (amiga_find_device(tmp)) {
775 devs[i] = tmp;
776 last_bus = i;
777 return (i);
778 }
779
780 return (-1);
781 }
782
783 LOCAL int
amiga_find_device(device)784 amiga_find_device(device)
785 char *device;
786 {
787 char tmp[256];
788 struct Node *DeviceLibNode = SysBase->DeviceList.lh_Head;
789
790 if (ami_debug)
791 printf("looking for %s ", device);
792
793 Forbid();
794 while (DeviceLibNode->ln_Succ) {
795 DeviceLibNode = DeviceLibNode->ln_Succ;
796 strcpy(tmp, DeviceLibNode->ln_Name);
797 strlwr(tmp);
798 if (strcmp(tmp, device) == 0) {
799 if (ami_debug)
800 printf(" ... found\n");
801 return (1);
802 }
803 }
804 Permit();
805
806 if (ami_debug)
807 printf(" ... not found\n");
808
809 return (0);
810 }
811