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