|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * a SCSI device
5: *
6: * Copyright 1995 Bernd Schmidt
7: * Copyright 1999 Patrick Ohly
8: */
9:
10: #include "sysconfig.h"
11: #include "sysdeps.h"
12:
13: #include "config.h"
14: #include "threaddep/penguin.h"
15: #include "options.h"
16: #include "memory.h"
17: #include "custom.h"
18: #include "readcpu.h"
19: #include "newcpu.h"
20: #include "disk.h"
21: #include "autoconf.h"
22: #include "filesys.h"
23: #include "execlib.h"
24: #include "native2amiga.h"
25: #include "scsidev.h"
26:
1.1.1.4 ! root 27: #include <stdio.h>
! 28:
1.1.1.3 root 29: /* the new libscg should always have a scsi_close */
30: #ifndef SCSI_CLOSE
31: #define SCSI_CLOSE
1.1 root 32: #endif
33:
1.1.1.3 root 34: typedef int BOOL;
1.1 root 35:
1.1.1.3 root 36: #include "scg/scgcmd.h"
37: #include "scg/scsitransp.h"
38: #include "scg/scsireg.h"
1.1 root 39:
1.1.1.3 root 40: /* our configure does not have a seperate UAE_SCSIDEV_THREADS */
41: #if defined(UAE_FILESYS_THREADS) && !defined(SCSI_IS_NOT_THREAD_SAFE)
42: #define UAE_SCSIDEV_THREADS
43: #endif
1.1 root 44:
1.1.1.3 root 45: #undef DEBUGME
1.1 root 46:
47: /****************** generic SCSI stuff stolen from cdrecord and scsitransp.c ***********/
48: static int scsierr(SCSI *scgp)
49: {
50: register struct scg_cmd *cp = scgp->scmd;
51:
52: if(cp->error != SCG_NO_ERROR ||
53: cp->ux_errno != 0 || *(u_char *)&cp->scb != 0)
54: return -1;
55: return 0;
56: }
57:
58: static int inquiry (SCSI *scgp, void *bp, int cnt)
59: {
60: struct scg_cmd *scmd = scgp->scmd;
61:
1.1.1.3 root 62: memset(bp, cnt, '\0');
63: memset((caddr_t)scmd, sizeof(*scmd), '\0');
1.1 root 64: scmd->addr = bp;
65: scmd->size = cnt;
66: scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
67: scmd->cdb_len = SC_G0_CDBLEN;
68: scmd->sense_len = CCS_SENSE_LEN;
69: scmd->target = scgp->target;
70: scmd->cdb.g0_cdb.cmd = SC_INQUIRY;
71: scmd->cdb.g0_cdb.lun = scgp->lun;
72: scmd->cdb.g0_cdb.count = cnt;
73:
74: scgp->cmdname = "inquiry";
75:
76: if (scsicmd(scgp) < 0)
77: return (-1);
78: return (0);
79: }
80:
81: static void print_product(struct scsi_inquiry *ip)
82: {
83: write_log ("'%.8s' ", ip->info);
84: write_log ("'%.16s' ", ip->ident);
85: write_log ("'%.4s' ", ip->revision);
86: if (ip->add_len < 31) {
87: write_log ("NON CCS ");
88: }
89: }
90:
1.1.1.3 root 91: /* get integer value from env or return default value, if unset */
92: static int getenvint (const char *varname, int def)
1.1 root 93: {
1.1.1.3 root 94: const char *val = getenv (varname);
95: return val ? atoi (val) : def;
96: }
97:
98: /* wrapper for the underlying combination of scsi_smalloc()/scsi_open() */
99: static SCSI *openscsi (int scsibus, int target, int lun)
100: {
101: SCSI *scgp = scsi_smalloc ();
102: if (!scgp) {
1.1 root 103: return NULL;
104: }
1.1.1.3 root 105:
106: scgp->debug = getenvint ("UAE_SCSI_DEBUG", 0);
107: scgp->kdebug = getenvint ("UAE_SCSI_KDEBUG", 0);
108: scgp->silent = getenvint ("UAE_SCSI_SILENT", 1);
1.1.1.4 ! root 109: scgp->verbose = getenvint ("UAE_SCSI_VERBOSE", 0);
1.1.1.3 root 110: scgp->scsibus = scsibus;
1.1 root 111: scgp->target = target;
112: scgp->lun = lun;
1.1.1.3 root 113:
114: if (!scsi_open(scgp, NULL, scsibus, target, lun)) {
115: scsi_sfree (scgp);
116: return NULL;
117: } else {
118: return scgp;
119: }
1.1 root 120: }
121:
122: static void closescsi (SCSI *scgp)
123: {
124: scsi_close (scgp);
1.1.1.3 root 125: scsi_sfree (scgp);
1.1 root 126: }
127:
128: /********************* start of our own code ************************/
129:
130: static int opencount = 0;
131: static SCSI *scgp; /* SCSI handle which is to be used by the main thread */
132: uae_sem_t scgp_sem;
133:
134:
135: /****************** unit handling *******************/
136:
137: struct scsidevdata {
138: int bus, target, lun; /* the real values */
139: int aunit; /* Amiga unit number, by default calculated like that: */
140: #define BTL2UNIT(bus, target, lun) \
141: (2 * (bus) + (target) / 8) * 100 + \
142: (lun) * 10 + \
143: (target % 8)
144: SCSI *scgp;
145: long max_dma;
1.1.1.3 root 146: int isatapi;
1.1 root 147: #ifdef UAE_SCSIDEV_THREADS
148: /* Threading stuff */
149: smp_comm_pipe requests;
150: penguin_id tid;
151: int thread_running;
152: uae_sem_t sync_sem;
153: #endif
154: };
155:
156: #define MAX_DRIVES 16
157: static struct scsidevdata drives[MAX_DRIVES];
158: static int num_drives;
159: static struct scsidevdata *get_scsidev_data (int unit)
160: {
161: int i;
162:
163: for (i = 0; i < num_drives; i++) {
164: if (unit == drives[i].aunit) {
165: return &drives[i];
166: }
167: }
168: return NULL;
169: }
170:
171: static struct scsidevdata *add_scsidev_data (int bus, int target, int lun, int aunit)
172: {
173: if (num_drives + 1 < MAX_DRIVES) {
174: memset(&drives[num_drives], 0, sizeof(drives[num_drives]));
175: drives[num_drives].bus = bus;
176: drives[num_drives].target = target;
177: drives[num_drives].lun = lun;
178: drives[num_drives].aunit = aunit;
1.1.1.3 root 179: #if !defined(UAE_SCSIDEV_THREADS)
1.1 root 180: drives[num_drives].scgp = scgp;
1.1.1.3 root 181: drives[num_drives].max_dma = scsi_bufsize (scgp, 512 * 1024);
1.1 root 182: #endif
1.1.1.3 root 183: /* check if this drive is an ATAPI drive */
184: scgp->scsibus = bus;
185: scgp->target = target;
186: scgp->lun = lun;
187: drives[num_drives].isatapi = scsi_isatapi (scgp);
1.1 root 188: return &drives[num_drives++];
189: }
190:
191: return NULL;
192: }
193:
194: static void *scsidev_penguin(void *);
195: static int start_thread (struct scsidevdata *sdd)
196: {
197: #ifdef UAE_SCSIDEV_THREADS
198: if (sdd->thread_running)
199: return 1;
200: init_comm_pipe (&sdd->requests, 10, 1);
201: uae_sem_init (&sdd->sync_sem, 0, 0);
202: start_penguin (scsidev_penguin, sdd, &sdd->tid);
203: uae_sem_wait (&sdd->sync_sem);
204: return sdd->thread_running;
205: #else
206: return 1;
207: #endif
208: }
209:
210: /************* Exec device functions ****************/
211:
212:
213: static uae_u32 scsidev_open (void)
214: {
215: uaecptr tmp1 = m68k_areg(regs, 1); /* IOReq */
216: uae_u32 unit = m68k_dreg (regs, 0);
217: struct scsidevdata *sdd;
218:
219: #ifdef DEBUGME
220: printf("scsidev_open(0x%x, %d)\n", tmp1, unit);
221: #endif
222:
223: /* Check unit number */
224: if ((sdd = get_scsidev_data (unit)) &&
225: start_thread (sdd)) {
226: opencount++;
227: put_word (m68k_areg(regs, 6)+32, get_word (m68k_areg(regs, 6)+32) + 1);
228: put_long (tmp1 + 24, unit); /* io_Unit */
229: put_byte (tmp1 + 31, 0); /* io_Error */
230: put_byte (tmp1 + 8, 7); /* ln_type = NT_REPLYMSG */
231: return 0;
232: }
233:
234: put_long (tmp1 + 20, (uae_u32)-1);
235: put_byte (tmp1 + 31, (uae_u8)-1);
236: return (uae_u32)-1;
237: }
238:
239: static uae_u32 scsidev_close (void)
240: {
241: #ifdef DEBUGME
242: printf("scsidev_close()\n");
243: #endif
244:
245: opencount--;
246: put_word (m68k_areg(regs, 6) + 32, get_word (m68k_areg(regs, 6) + 32) - 1);
247:
248: return 0;
249: }
250:
251: static uae_u32 scsidev_expunge (void)
252: {
253: #ifdef DEBUGME
254: printf("scsidev_expunge()\n");
255: #endif
256: return 0; /* Simply ignore this one... */
257: }
258:
259: #define MODE_SELECT_6 0x15
260: #define MODE_SENSE_6 0x1A
261: #ifndef MODE_SENSE_10
262: #define MODE_SELECT_10 0x55
263: #define MODE_SENSE_10 0x5A
264: #endif
265:
1.1.1.4 ! root 266:
! 267: #ifdef DEBUG_CDR
! 268: /* please ignore this code - it can be used to debug raw CD-R writing... */
! 269:
! 270: /*
! 271: ** convert time in (BCD) min:sec:frame to block address
! 272: */
! 273: typedef signed char BYTE;
! 274: typedef unsigned char UBYTE;
! 275: typedef long LONG;
! 276: typedef BYTE BCD;
! 277: typedef BYTE WORD[2];
! 278: #define BCD_DEC(x) (((x) >> 4) * 10 + ((x) & 0xF))
! 279: static LONG TestNegativeTime(LONG block)
! 280: {
! 281: /* block -151 == 99:59:74
! 282: -150 == 100:00:00 = 00:00:00 */
! 283: if (block > (97 * 60 * 75))
! 284: {
! 285: /* must be a negative block */
! 286: block -= 100 * 60 * 75;
! 287: }
! 288: return block;
! 289: }
! 290: static LONG BCDTime2Block(UBYTE min, UBYTE sec, UBYTE frame)
! 291: {
! 292: return(TestNegativeTime((LONG)((BCD_DEC(min) * 60 + BCD_DEC(sec)) * 75 + BCD_DEC(frame) - 2 * 75)));
! 293: }
! 294: static LONG Time2Block(UBYTE min, UBYTE sec, UBYTE frame)
! 295: {
! 296: return(TestNegativeTime((LONG)((min * 60 + sec) * 75 + frame - 2 * 75)));
! 297: }
! 298: static LONG BCDTime2Block_Pointer (UBYTE *p)
! 299: {
! 300: return BCDTime2Block (p[0], p[1], p[2]);
! 301: }
! 302: static LONG Time2Block_Pointer (UBYTE *p)
! 303: {
! 304: return Time2Block (p[0], p[1], p[2]);
! 305: }
! 306: #endif
! 307:
1.1 root 308: static void scsidev_do_scsi (struct scsidevdata *sdd, uaecptr request)
309: {
310: SCSI *scgp = sdd->scgp;
311: struct scg_cmd *scmd = scgp->scmd;
312: uaecptr acmd = get_long (request + 40);
313: uaecptr scsi_data = get_long (acmd + 0);
314: uae_u32 scsi_len = get_long (acmd + 4);
315: uaecptr scsi_cmd = get_long (acmd + 12);
316: uae_u16 scsi_cmd_len = get_word (acmd + 16);
317: uae_u8 scsi_flags = get_byte (acmd + 20);
318: uaecptr scsi_sense = get_long (acmd + 22);
319: uae_u16 scsi_sense_len = get_word (acmd + 26);
320: int sactual = 0;
321: addrbank *bank_data = &get_mem_bank (scsi_data);
322: addrbank *bank_cmd = &get_mem_bank (scsi_cmd);
323:
324: /* do transfer directly to and from Amiga memory */
325: if (!bank_data || !bank_data->check (scsi_data, scsi_len) ||
326: !bank_cmd || !bank_cmd->check (scsi_cmd, scsi_cmd_len)) {
327: put_byte (request + 31, (uae_u8)-5); /* IOERR_BADADDRESS */
328: return;
329: }
330:
1.1.1.3 root 331: #ifdef SCSI_IS_NOT_THREAD_SAFE
1.1 root 332: uae_sem_wait (&scgp_sem);
333: #endif
334:
1.1.1.4 ! root 335: scmd->timeout = 80 * 60; /* the Amiga does not tell us how long the timeout shall be, so make it _very_ long (specified in seconds) */
1.1 root 336: scmd->addr = bank_data->xlateaddr (scsi_data);
337: scmd->size = scsi_len;
338: scmd->flags = ((scsi_flags & 1) ? SCG_RECV_DATA : 0) | SCG_DISRE_ENA;
339: scmd->cdb_len = scsi_cmd_len;
340: memcpy(&scmd->cdb, bank_cmd->xlateaddr (scsi_cmd), scsi_cmd_len);
341: scmd->target = sdd->target;
342: scmd->sense_len = (scsi_flags & 4) ? 4 : /* SCSIF_OLDAUTOSENSE */
343: (scsi_flags & 2) ? scsi_sense_len : /* SCSIF_AUTOSENSE */
344: -1;
345: scmd->sense_count = 0;
346: *(uae_u8 *)&scmd->scb = 0;
347:
1.1.1.4 ! root 348: #ifdef DEBUG_CDR
! 349: /* please ignore this code - it can be used to debug raw CD-R writing... */
! 350: if (!(scsi_len % 2368)) {
! 351: /* Structure for generating bytes 2353...2368 if writing in ultra raw mode */
! 352: typedef struct QDATAtag {
! 353: BYTE ControlAdr;
! 354: BCD Tno;
! 355: BCD Point;
! 356: BCD Min;
! 357: BCD Sec;
! 358: BCD Frame;
! 359: BYTE Zero;
! 360: BCD PMin;
! 361: BCD PSec;
! 362: BCD PFrame;
! 363: WORD Crc;
! 364: BYTE Reserved[3];
! 365: BYTE PChannel;
! 366: } QDATA;
! 367:
! 368: int i = scsi_len / 2368;
! 369: QDATA *data = (QDATA *)&((unsigned char *)scmd->addr)[2352];
! 370: for (; i > 0; i--, data = (QDATA *)&((unsigned char *)data)[2368]) {
! 371: printf ("$%02x: $%02x $%02x | $%02x:$%02x:$%02x = %6ld | $%02x | $%02x:$%02x:$%02x = %6ld\n",
! 372: (int)data->ControlAdr, (int)*(UBYTE *)&data->Tno, (int)*(UBYTE *)&data->Point,
! 373: (int)*(UBYTE *)&data->Min, (int)*(UBYTE *)&data->Sec, (int)*(UBYTE *)&data->Frame,
! 374: BCDTime2Block_Pointer (&data->Min) + 150,
! 375: *(UBYTE *)&data->Zero,
! 376: *(UBYTE *)&data->PMin, *(UBYTE *)&data->PSec, *(UBYTE *)&data->PFrame,
! 377: BCDTime2Block_Pointer (&data->PMin));
! 378: }
! 379: fflush (stdout);
1.1.1.3 root 380: }
1.1.1.4 ! root 381: #endif
! 382:
1.1 root 383: scgp->scsibus = sdd->bus;
384: scgp->target = sdd->target;
385: scgp->lun = sdd->lun;
1.1.1.4 ! root 386: scgp->cmdname = "???";
! 387: scgp->curcmdname = "???";
1.1 root 388:
1.1.1.3 root 389: /* replace MODE_SELECT/SENSE_6 if we access a ATAPI drive,
390: otherwise send it now */
391: if (sdd->isatapi &&
1.1 root 392: (scmd->cdb.g0_cdb.cmd == MODE_SELECT_6 ||
393: scmd->cdb.g0_cdb.cmd == MODE_SENSE_6)) {
394: uae_u8 buffer[256 + 2], *data = scmd->addr, *tmp;
395: int len = 0, page_len, i;
396: int do_it = 1;
397: uae_u8 sp = scmd->cdb.g0_cdb.high_addr & 1;
398: uae_u8 alloc_len = scmd->cdb.g0_cdb.count;
399: uae_u8 pcf_page_code = scmd->cdb.g0_cdb.mid_addr;
400: uae_u8 cmd = scmd->cdb.g0_cdb.cmd;
401:
402: memset (&scmd->cdb.g1_cdb, 0, sizeof(scmd->cdb.g1_cdb));
403: if (cmd == MODE_SELECT_6) {
404: /* expand parameter list */
405: tmp = data;
406: buffer[len++] = *tmp++; /* first byte, should be 0 */
407: buffer[len++] = 0; /* reserved */
408: buffer[len++] = *tmp++; /* medium type */
409: buffer[len++] = 0; *tmp++; /* ignore host application code */
410: for (i = 0; i < 4; i++) {
411: buffer[len++] = 0;
412: }
413: if (*tmp) {
414: /* skip block descriptor */
415: tmp += 8;
416: }
417: tmp++;
418: page_len = scsi_len - (tmp - data);
419: if (page_len > 0) {
420: memcpy (&buffer[len], tmp, page_len);
421: len += page_len;
422:
423: scmd->cdb.g1_cdb.cmd = MODE_SELECT_10;
424: scmd->cdb.g1_cdb.lun = sdd->lun;
425: scmd->cdb.g1_cdb.res = 1 << 3; /* PF bit */
426: scmd->cdb.g1_cdb.reladr = sp;
427: scmd->cdb.g1_cdb.count[0] = len >> 8;
428: scmd->cdb.g1_cdb.count[1] = len;
429: } else {
430: do_it = 0;
431: scmd->error = 0;
432: *(uae_u8 *)&scmd->scb = 0;
433: scmd->ux_errno = 0;
434: }
435: } else {
436: /* MODE_SENSE_6 */
437: len = alloc_len + 2;
438: scmd->cdb.g1_cdb.cmd = MODE_SENSE_10;
439: scmd->cdb.g1_cdb.lun = sdd->lun;
440: scmd->cdb.g1_cdb.addr[0] = pcf_page_code;
441: scmd->cdb.g1_cdb.count[0] = len >> 8;
442: scmd->cdb.g1_cdb.count[1] = len;
443: }
444: if (do_it) {
445: scmd->cdb_len = 10;
446: scmd->addr = buffer;
447: scmd->size = len;
448: scmd->sense_count = 0;
449: *(uae_u8 *)&scmd->scb = 0;
450:
451: scsicmd (scgp);
452:
453: if (cmd == MODE_SENSE_6 &&
454: !scmd->error &&
455: !scmd->ux_errno &&
456: !*(uae_u8 *)&scmd->scb) {
457: int req_len = len;
458:
459: /* compress result */
460: tmp = buffer;
461: len = 0;
462: tmp++; /* skip first byte of length - should better be zero */
463: data[len++] = *tmp++; /* mode data length */
464: data[len++] = *tmp++; /* medium type */
465: data[len++] = 0; /* host application type */
466: data[len++] = 0; /* block descr length */
467: tmp += 4;
468: if (*tmp) {
469: /* skip block descr - should not happen */
470: tmp += *tmp;
471: }
472: tmp++;
473: memcpy (&data[len], tmp, req_len - (tmp - buffer));
474: }
475: }
1.1.1.3 root 476: } else {
477: scsicmd (scgp);
1.1 root 478: }
479:
480: put_word (acmd + 18, scmd->error == SCG_FATAL ? 0 : scsi_cmd_len); /* fake scsi_CmdActual */
481: put_byte (acmd + 21, *(uae_u8 *)&scmd->scb); /* scsi_Status */
482: if (*(uae_u8 *)&scmd->scb) {
483: put_byte (request + 31, 45); /* HFERR_BadStatus */
484:
485: /* copy sense? */
486: for (sactual = 0;
487: scsi_sense && sactual < scsi_sense_len && sactual < scmd->sense_count;
488: sactual++) {
489: put_byte (scsi_sense + sactual, scmd->u_sense.cmd_sense[sactual]);
490: }
491: put_long (acmd + 8, 0); /* scsi_Actual */
492: } else {
493: int i;
494:
495: for (i = 0; i < scsi_sense_len; i++) {
496: put_byte (scsi_sense + i, 0);
497: }
498: sactual = 0;
499:
500: if (scmd->error != SCG_NO_ERROR ||
501: scmd->ux_errno != 0) {
1.1.1.3 root 502: /* we might have been limited by the hosts DMA limits,
503: which is usually indicated by ENOMEM */
504: if (scsi_len > (unsigned int)sdd->max_dma &&
505: scmd->ux_errno == ENOMEM) {
506: put_byte (request + 31, (uae_u8)-4); /* IOERR_BADLENGTH */
507: } else {
508: put_byte (request + 31, 20); /* io_Error, but not specified */
509: put_long (acmd + 8, 0); /* scsi_Actual */
510: }
1.1 root 511: } else {
512: put_byte (request + 31, 0);
513: put_long (acmd + 8, scsi_len - scmd->resid); /* scsi_Actual */
514: }
515: }
516: put_word (acmd + 28, sactual);
517:
1.1.1.3 root 518: #ifdef SCSI_IS_NOT_THREAD_SAFE
1.1 root 519: uae_sem_post (&scgp_sem);
520: #endif
521: }
522:
523: static void scsidev_do_io (struct scsidevdata *sdd, uaecptr request)
524: {
525: uae_u32 tmp2, dataptr, offset;
526:
527: tmp2 = get_word (request+28); /* io_Command */
528: switch (tmp2) {
529: case 28:
530: /* HD_SCSICMD */
531: scsidev_do_scsi (sdd, request);
532: break;
533: default:
534: /* Command not understood. */
535: put_byte (request+31, (uae_u8)-3); /* io_Error */
536: break;
537: }
538: #ifdef DEBUGME
539: printf ("scsidev: did io: sdd = 0x%x\n", sdd);
540: printf ("scsidev: did io: request = %08lx\n", (unsigned long)request);
541: printf ("scsidev: did io: error = %d\n", (int)get_word(request+31));
542: #endif
543: }
544:
545:
546: static uae_u32 scsidev_beginio (void)
547: {
548: uae_u32 request = m68k_areg(regs, 1);
549: int unit = get_long (request + 24);
550: struct scsidevdata *sdd = get_scsidev_data (unit);
551:
552: #ifdef DEBUGME
553: printf ("scsidev_begin_io: sdd = 0x%x\n", sdd);
554: printf ("scsidev_begin_io: request = %08lx\n", (unsigned long)request);
555: printf ("scsidev_begin_io: cmd = %d\n", (int)get_word(request+28));
556: #endif
557:
558: put_byte (request+8, NT_MESSAGE);
559: put_byte (request+31, 0); /* no error yet */
560:
561: #ifdef UAE_SCSIDEV_THREADS
562: {
563: uae_pt data;
564:
565: /* clear IOF_QUICK */
566: put_byte (request+30, get_byte (request+30) & ~1);
567: /* forward to unit thread */
568: write_comm_pipe_u32 (&sdd->requests, request, 1);
569: return 0;
570: }
571: #else
572: put_byte (request+30, get_byte (request+30) & ~1);
573: scsidev_do_io (sdd, request);
574: return get_byte (request+31); /* do we really have to return io_Error? */
575: #endif
576: }
577:
578: #ifdef UAE_SCSIDEV_THREADS
579: static void *scsidev_penguin (void *sddv)
580: {
581: struct scsidevdata *sdd = sddv;
582:
583: #ifdef DEBUGME
584: printf ("scsidev_penguin: sdd = 0x%x ready\n", sdd);
585: #endif
586: /* init SCSI */
1.1.1.3 root 587: if (!(sdd->scgp = openscsi (sdd->bus, sdd->target, sdd->lun)) ||
588: (sdd->max_dma = scsi_bufsize (sdd->scgp, 512 * 1024)) <= 0) {
1.1 root 589: sdd->thread_running = 0;
590: uae_sem_post (&sdd->sync_sem);
591: return 0;
592: }
593: sdd->thread_running = 1;
594: uae_sem_post (&sdd->sync_sem);
595:
596: for (;;) {
597: uaecptr request;
598:
599: request = (uaecptr)read_comm_pipe_u32_blocking (&sdd->requests);
600: #ifdef DEBUGME
601: printf ("scsidev_penguin: sdd = 0x%x\n", sdd);
602: printf ("scsidev_penguin: req = %08lx\n", (unsigned long)request);
603: printf ("scsidev_penguin: cmd = %d\n", (int)get_word(request+28));
604: #endif
605: if (!request) {
606: printf ("scsidev_penguin: going down with 0x%x\n", sdd->sync_sem);
607: /* Death message received. */
608: sdd->thread_running = 0;
609: uae_sem_post (&sdd->sync_sem);
610: /* Die. */
611: return 0;
612: }
613:
614: scsidev_do_io (sdd, request);
1.1.1.2 root 615: uae_ReplyMsg (request);
1.1 root 616: }
617: return 0;
618: }
619: #endif
620:
621:
622: static uae_u32 scsidev_abortio (void)
623: {
624: return (uae_u32)-3;
625: }
626:
627: static uae_u32 scsidev_init (void)
628: {
629: #ifdef DEBUGME
630: printf("scsidev_init()\n");
631: #endif
632:
633: if (scgp) {
634: /* we still have everything in place */
635: return m68k_dreg (regs, 0); /* device base */
636: }
637:
638: /* init global SCSI */
1.1.1.3 root 639: if (!(scgp = openscsi (-1, -1, -1))) {
1.1 root 640: return 0;
641: }
642:
643: uae_sem_init (&scgp_sem, 0, 1);
644:
645: /* add all units we find */
646: for (scgp->scsibus=0; scgp->scsibus < 8; scgp->scsibus++) {
647: if (!scsi_havebus(scgp, scgp->scsibus))
648: continue;
649: printf("scsibus%d:\n", scgp->scsibus);
650: for (scgp->target=0; scgp->target < 16; scgp->target++) {
651: struct scsi_inquiry inq;
652: scgp->lun = 0;
653: if (inquiry (scgp, &inq, sizeof(inq))) {
654: continue;
655: }
656: for (scgp->lun=0; scgp->lun < 8; scgp->lun++) {
657: if (!inquiry (scgp, &inq, sizeof(inq))) {
658: int aunit = BTL2UNIT(scgp->scsibus, scgp->target, scgp->lun);
1.1.1.3 root 659: struct scsidevdata *sdd;
1.1 root 660:
661: write_log (" %2.01d,%d (= %3.d): ", scgp->target, scgp->lun, aunit);
662: print_product (&inq);
1.1.1.3 root 663: sdd = add_scsidev_data (scgp->scsibus, scgp->target, scgp->lun, aunit);
664: write_log (!sdd ? " - init failed ???" : sdd->isatapi ? " - ATAPI" : " - SCSI");
1.1 root 665: write_log ("\n");
666: }
667: }
668: }
669: }
670: return m68k_dreg (regs, 0); /* device base */
671: }
672:
673: static uaecptr ROM_scsidev_resname = 0,
674: ROM_scsidev_resid = 0,
675: ROM_scsidev_init = 0;
676:
677: uaecptr scsidev_startup (uaecptr resaddr)
678: {
679: #ifdef DEBUGME
680: printf("scsidev_startup(0x%x)\n", resaddr);
681: #endif
682: /* Build a struct Resident. This will set up and initialize
683: * the uaescsi.device */
684: put_word(resaddr + 0x0, 0x4AFC);
685: put_long(resaddr + 0x2, resaddr);
686: put_long(resaddr + 0x6, resaddr + 0x1A); /* Continue scan here */
687: put_word(resaddr + 0xA, 0x8101); /* RTF_AUTOINIT|RTF_COLDSTART; Version 1 */
688: put_word(resaddr + 0xC, 0x0305); /* NT_DEVICE; pri 05 */
689: put_long(resaddr + 0xE, ROM_scsidev_resname);
690: put_long(resaddr + 0x12, ROM_scsidev_resid);
691: put_long(resaddr + 0x16, ROM_scsidev_init); /* calls scsidev_init */
692: resaddr += 0x1A;
693:
694: return resaddr;
695: }
696:
697: void scsidev_install (void)
698: {
699: uae_u32 functable, datatable;
700: uae_u32 initcode, openfunc, closefunc, expungefunc;
701: uae_u32 beginiofunc, abortiofunc;
702:
703: #ifdef DEBUGME
704: printf("scsidev_install(): 0x%x\n", here ());
705: #endif
706:
707: ROM_scsidev_resname = ds ("uaescsi.device");
708: ROM_scsidev_resid = ds ("UAE scsi.device 0.1");
709:
710: /* initcode */
711: initcode = here ();
712: calltrap (deftrap (scsidev_init)); dw (RTS);
713:
714: /* Open */
715: openfunc = here ();
716: calltrap (deftrap (scsidev_open)); dw (RTS);
717:
718: /* Close */
719: closefunc = here ();
720: calltrap (deftrap (scsidev_close)); dw (RTS);
721:
722: /* Expunge */
723: expungefunc = here ();
724: calltrap (deftrap (scsidev_expunge)); dw (RTS);
725:
726: /* BeginIO */
727: beginiofunc = here ();
728: calltrap (deftrap (scsidev_beginio));
729: #ifndef UAE_SCSIDEV_THREADS
730: /* don't reply when using threads - native2amiga's Reply() does that */
731: dw (0x48E7); dw (0x8002); /* movem.l d0/a6,-(a7) */
732: dw (0x0829); dw (0); dw (30); /* btst #0,30(a1) */
733: dw (0x6608); /* bne.b +8 */
734: dw (0x2C78); dw (0x0004); /* move.l 4,a6 */
735: dw (0x4EAE); dw (-378); /* jsr ReplyMsg(a6) */
736: dw (0x4CDF); dw (0x4001); /* movem.l (a7)+,d0/a6 */
737: #endif
738: dw (RTS);
739:
740: /* AbortIO */
741: abortiofunc = here ();
742: calltrap (deftrap (scsidev_abortio)); dw (RTS);
743:
744: /* FuncTable */
745: functable = here ();
746: dl (openfunc); /* Open */
747: dl (closefunc); /* Close */
748: dl (expungefunc); /* Expunge */
749: dl (EXPANSION_nullfunc); /* Null */
750: dl (beginiofunc); /* BeginIO */
751: dl (abortiofunc); /* AbortIO */
752: dl (0xFFFFFFFFul); /* end of table */
753:
754: /* DataTable */
755: datatable = here ();
756: dw (0xE000); /* INITBYTE */
757: dw (0x0008); /* LN_TYPE */
758: dw (0x0300); /* NT_DEVICE */
759: dw (0xC000); /* INITLONG */
760: dw (0x000A); /* LN_NAME */
761: dl (ROM_scsidev_resname);
762: dw (0xE000); /* INITBYTE */
763: dw (0x000E); /* LIB_FLAGS */
764: dw (0x0600); /* LIBF_SUMUSED | LIBF_CHANGED */
765: dw (0xD000); /* INITWORD */
766: dw (0x0014); /* LIB_VERSION */
767: dw (0x0004); /* 0.4 */
768: dw (0xD000); /* INITWORD */
769: dw (0x0016); /* LIB_REVISION */
770: dw (0x0000); /* end of table already ??? */
771: dw (0xC000); /* INITLONG */
772: dw (0x0018); /* LIB_IDSTRING */
773: dl (ROM_scsidev_resid);
774: dw (0x0000); /* end of table */
775:
776: ROM_scsidev_init = here ();
777: dl (0x00000100); /* size of device base */
778: dl (functable);
779: dl (datatable);
780: dl (initcode);
781: }
782:
783: void scsidev_reset (void)
784: {
785: #ifdef DEBUGME
786: printf("scsidev_reset()\n");
787: #endif
788:
789: #ifdef SCSI_CLOSE
790: #ifdef UAE_SCSIDEV_THREADS
791: {
792: int i;
793:
794: for (i = 0; i < num_drives; i++) {
1.1.1.3 root 795: if (!drives[i].thread_running) {
796: continue;
797: }
798: write_comm_pipe_int (&drives[i].requests, 0, 1);
799: uae_sem_wait (&drives[i].sync_sem);
1.1 root 800: }
801: num_drives = 0;
802: }
803: #endif
804:
805: if (scgp) {
806: closescsi (scgp);
807: scgp = NULL;
808: }
809: #endif
810:
811: opencount = 0;
812: }
813:
814: void scsidev_start_threads (void)
815: {
816: #ifdef DEBUGME
817: printf("scsidev_start_threads()\n");
818: #endif
819: }
820:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.