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