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