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