2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
13 /* @(#)scsi-wnt.c 1.45 04/07/19 Copyright 1998-2004 J. Schilling, A.L. Faber, J.A. Key */
15 * Interface for the Win32 ASPI library.
16 * You need wnaspi32.dll and aspi32.sys
17 * Both can be installed from ASPI_ME
19 * Warning: you may change this source, but if you do that
20 * you need to change the _usal_version and _usal_auth* string below.
21 * You may not return "schily" for an SCG_AUTHOR request anymore.
22 * Choose your name instead of "schily" and make clear that the version
23 * string is related to a modified source.
25 * Copyright (c) 1998-2004 J. Schilling
26 * Copyright (c) 1999 A.L. Faber for the first implementation
29 * - DMA resid handling
30 * - better handling of maxDMA
31 * - SCSI reset support
34 * This program is free software; you can redistribute it and/or modify
35 * it under the terms of the GNU General Public License version 2
36 * as published by the Free Software Foundation.
38 * This program is distributed in the hope that it will be useful,
39 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41 * GNU General Public License for more details.
43 * You should have received a copy of the GNU General Public License along with
44 * this program; see the file COPYING. If not, write to the Free Software
45 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
50 * Include for Win32 ASPI AspiRouter
52 * NOTE: aspi-win32.h includes Windows.h and Windows.h includes
53 * Base.h which has a second typedef for BOOL.
54 * We define BOOL to make all local code use BOOL
55 * from Windows.h and use the hidden __SBOOL for
56 * our global interfaces.
58 #define BOOL WBOOL /* This is the Win BOOL */
59 #define format __format
60 #include <usal/aspi-win32.h>
61 #include <usal/spti-wnt.h>
64 #ifdef __CYGWIN32__ /* Use dlopen() */
69 * Warning: you may change this source, but if you do that
70 * you need to change the _usal_version and _usal_auth* string below.
71 * You may not return "schily" for an SCG_AUTHOR request anymore.
72 * Choose your name instead of "schily" and make clear that the version
73 * string is related to a modified source.
75 static char _usal_trans_version[] = "scsi-wnt.c-1.45"; /* The version for this transport*/
76 static char _usal_itrans_version[] = "SPTI-scsi-wnt.c-1.45"; /* The version for SPTI */
79 * Local defines and constants
81 /*#define DEBUG_WNTASPI*/
83 #define MAX_SCG 16 /* Max # of SCSI controllers */
84 #define MAX_TGT 16 /* Max # of SCSI Targets */
85 #define MAX_LUN 8 /* Max # of SCSI LUNs */
92 char *filenames[MAX_SCG][MAX_TGT][MAX_LUN];
95 #define usallocal(p) ((struct usal_local *)((p)->local))
101 static DWORD (*pfnGetASPI32SupportInfo)(void) = NULL;
102 static DWORD (*pfnSendASPI32Command)(LPSRB) = NULL;
103 static BOOL (*pfnGetASPI32Buffer)(PASPI32BUFF) = NULL;
104 static BOOL (*pfnFreeASPI32Buffer)(PASPI32BUFF) = NULL;
105 static BOOL (*pfnTranslateASPI32Address)(PDWORD, PDWORD) = NULL;
107 static int DriverLoaded = 0; /* ASPI or SPTI */
108 static HANDLE hAspiLib = NULL; /* Used for Loadlib */
110 #define MAX_DMA_WNT (63L*1024L) /* ASPI-Driver allows up to 64k ??? */
113 * Local function prototypes
115 static void exit_func(void);
117 static void DebugScsiSend(SCSI *usalp, SRB_ExecSCSICmd *s, int bDisplayBuffer);
119 static void copy_sensedata(SRB_ExecSCSICmd *cp, struct usal_cmd *sp);
120 static void set_error(SRB_ExecSCSICmd *cp, struct usal_cmd *sp);
121 static BOOL open_driver(SCSI *usalp);
122 static BOOL load_aspi(SCSI *usalp);
123 static BOOL close_driver(void);
124 static int ha_inquiry(SCSI *usalp, int id, SRB_HAInquiry *ip);
126 static int resetSCSIBus(SCSI *usalp);
128 static int scsiabort(SCSI *usalp, SRB_ExecSCSICmd *sp);
131 /* SPTI Start ---------------------------------------------------------------*/
133 * From scsipt.c - Copyright (C) 1999 Jay A. Key
134 * Homepage: http://akrip.sourceforge.net/
135 * Native NT support functions via the SCSI Pass Through interface instead
136 * of ASPI. Although based on information from the NT 4.0 DDK from
137 * Microsoft, the information has been sufficiently distilled to allow
138 * compilation w/o having the DDK installed.
139 * added to scsi-wnt.c by Richard Stemmer, rs@epost.de
140 * See http://www.ste-home.de/cdrtools-spti/
143 #define PREFER_SPTI 1 /* Prefer SPTI if available, else try ASPI, force ASPI with dev=ASPI: */
144 /* #define CREATE_NONSHARED 1 */ /* open CDROM-Device not SHARED if possible */
145 /* #define _DEBUG_SCSIPT 1 */
147 FILE *usalp_errfile; /* File for SPTI-Debug-Messages */
150 #define SENSE_LEN_SPTI 32 /* Sense length for ASPI is only 14 */
151 #define NUM_MAX_NTSCSI_DRIVES 26 /* a: ... z: */
152 #define NUM_FLOPPY_DRIVES 2
153 #define NUM_MAX_NTSCSI_HA NUM_MAX_NTSCSI_DRIVES
155 #define NTSCSI_HA_INQUIRY_SIZE 36
157 #define SCSI_CMD_INQUIRY 0x12
160 BYTE ha; /* SCSI Bus # */
161 BYTE tgt; /* SCSI Target # */
162 BYTE lun; /* SCSI Lun # */
163 BYTE PortNumber; /* SCSI Card # (\\.\SCSI%d) */
164 BYTE PathId; /* SCSI Bus/Channel # on card n */
165 BYTE driveLetter; /* Win32 drive letter (e.g. c:) */
166 BOOL bUsed; /* Win32 drive letter is used */
167 HANDLE hDevice; /* Win32 handle for ioctl() */
168 BYTE inqData[NTSCSI_HA_INQUIRY_SIZE];
173 DRIVE drive[NUM_MAX_NTSCSI_DRIVES];
176 static int InitSCSIPT(SCSI *usalp);
177 static int DeinitSCSIPT(void);
178 static void GetDriveInformation(BYTE i, DRIVE *pDrive);
179 static BYTE SPTIGetNumAdapters(void);
180 static BYTE SPTIGetDeviceIndex(BYTE ha, BYTE tgt, BYTE lun);
181 static DWORD SPTIHandleHaInquiry(LPSRB_HAInquiry lpsrb);
182 static DWORD SPTIExecSCSICommand(LPSRB_ExecSCSICmd lpsrb, int sptTimeOutValue, BOOL bBeenHereBefore);
183 static HANDLE GetFileHandle(BYTE i, BOOL openshared);
185 static BOOL bSCSIPTInit = FALSE;
186 static SPTIGLOBAL sptiglobal;
187 static BOOL UsingSPTI = FALSE;
188 static BOOL ForceAccess = FALSE;
189 static int sptihamax;
190 static USHORT sptihasortarr[NUM_MAX_NTSCSI_HA];
193 * Initialization of SCSI Pass Through Interface code. Responsible for
194 * setting up the array of SCSI devices. This code will be a little
195 * different from the normal code -- it will query each drive letter from
196 * C: through Z: to see if it is a CD. When we identify a CD, we then
197 * send CDB with the INQUIRY command to it -- NT will automagically fill in
198 * the PathId, TargetId, and Lun for us.
200 static int InitSCSIPT(SCSI *usalp) {
207 char adapter_name[20];
211 char InquiryBuffer[2048];
212 PSCSI_ADAPTER_BUS_INFO ai;
220 * Detect all Busses on all SCSI-Adapters
221 * Fill up map array that allows us to later assign devices to
227 snprintf(adapter_name, sizeof (adapter_name), "\\\\.\\SCSI%d:", i);
228 fh = CreateFile(adapter_name, GENERIC_READ | GENERIC_WRITE,
229 FILE_SHARE_READ | FILE_SHARE_WRITE,
231 OPEN_EXISTING, 0, NULL);
232 if (fh != INVALID_HANDLE_VALUE) {
233 status = DeviceIoControl(fh,
234 IOCTL_SCSI_GET_INQUIRY_DATA,
242 ai = (PSCSI_ADAPTER_BUS_INFO) InquiryBuffer;
243 for (bus = 0; bus < ai->NumberOfBusses; bus++) {
244 sptihasortarr[sptihamax] = ((i<<8) | bus);
251 } while (fh != INVALID_HANDLE_VALUE);
254 memset(&sptiglobal, 0, sizeof (SPTIGLOBAL));
255 for (i = 0; i < NUM_MAX_NTSCSI_DRIVES; i++)
256 sptiglobal.drive[i].hDevice = INVALID_HANDLE_VALUE;
258 for (i = NUM_FLOPPY_DRIVES; i < NUM_MAX_NTSCSI_DRIVES; i++) {
259 snprintf(buf, sizeof (buf), "%c:\\", (char)('A'+i));
260 uDriveType = GetDriveType(buf);
262 if (uDriveType == DRIVE_CDROM) {
266 GetDriveInformation(i, &sptiglobal.drive[i]);
268 if (sptiglobal.drive[i].bUsed) {
270 hasortval = (sptiglobal.drive[i].PortNumber<<8) | sptiglobal.drive[i].PathId;
271 for (j = 0; j < sptihamax; j++) {
272 if (hasortval <= sptihasortarr[j])
275 if (j == sptihamax) {
276 sptihasortarr[j] = hasortval;
278 } else if (hasortval < sptihasortarr[j]) {
279 memmove(&sptihasortarr[j+1], &sptihasortarr[j], (sptihamax-j) * sizeof (USHORT));
280 sptihasortarr[j] = hasortval;
284 /* shortcut for device names, remember the hit */
285 if(uDriveType==DRIVE_CDROM && usalp->local) {
286 /* printf("seen, %d at %d, %d, %d\n", sptiglobal.drive[i].driveLetter, sptiglobal.drive[i].ha, sptiglobal.drive[i].tgt, sptiglobal.drive[i].lun); */
287 if(usallocal(usalp)->drive_wanted && *buf==toupper(usallocal(usalp)->drive_wanted))
289 /* don't keep the names, serial search in _natname is sufficient */
294 /* looks like a workaround for diverging ASPI and SPTI hostadapter numbers,
295 most likely an attempt to keep the world of fake numbers
299 for (i = NUM_FLOPPY_DRIVES; i < NUM_MAX_NTSCSI_DRIVES; i++)
300 if (sptiglobal.drive[i].bUsed)
301 for (j = 0; j < sptihamax; j++) {
302 if (sptihasortarr[j] == ((sptiglobal.drive[i].PortNumber<<8) | sptiglobal.drive[i].PathId)) {
303 sptiglobal.drive[i].ha = j;
308 sptiglobal.numAdapters = SPTIGetNumAdapters();
312 usal_scsibus(usalp)=sptiglobal.drive[id_wanted].ha;
313 usal_target(usalp) =sptiglobal.drive[id_wanted].tgt;
314 usal_lun(usalp) =sptiglobal.drive[id_wanted].lun;
318 fprintf(stderr, "named SCSIPT drive type %d found as %c, choosing %d, %d, %d\n",
342 for (i = NUM_FLOPPY_DRIVES; i < NUM_MAX_NTSCSI_DRIVES; i++) {
343 if (sptiglobal.drive[i].bUsed) {
344 CloseHandle(sptiglobal.drive[i].hDevice);
348 sptiglobal.numAdapters = SPTIGetNumAdapters();
350 memset(&sptiglobal, 0, sizeof (SPTIGLOBAL));
357 * Returns the number of "adapters" present.
360 SPTIGetNumAdapters(void)
364 BYTE numAdapters = 0;
369 * PortNumber 0 should exist, so pre-mark it. This avoids problems
370 * when the primary IDE drives are on PortNumber 0, but can't be opened
371 * because of insufficient privelege (ie. non-admin).
374 for (i = 0; i < NUM_MAX_NTSCSI_DRIVES; i++) {
375 if (sptiglobal.drive[i].bUsed)
376 buf[sptiglobal.drive[i].ha] = 1;
379 for (i = 0; i <= 255; i++)
381 numAdapters = (BYTE)(i + 1);
385 return (numAdapters);
394 memset(&osver, 0, sizeof (osver));
395 osver.dwOSVersionInfoSize = sizeof (osver);
396 GetVersionEx(&osver);
397 if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
399 * Win2000 is NT-5.0, Win-XP is NT-5.1
401 if (osver.dwMajorVersion > 4)
408 w2kstyle_create(void)
413 memset(&osver, 0, sizeof (osver));
414 osver.dwOSVersionInfoSize = sizeof (osver);
415 GetVersionEx(&osver);
416 if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
418 * Win2000 is NT-5.0, Win-XP is NT-5.1
420 if (osver.dwMajorVersion > 4)
423 if (osver.dwMajorVersion == 4) { /* NT-4.x */
424 char *vers = osver.szCSDVersion;
426 if (strlen(vers) == 0)
430 * Servicepack is installed, skip over non-digit part
432 while (*vers != '\0' && !isdigit(*vers))
437 if (isdigit(vers[0]) &&
438 (atoi(vers) >= 4 || isdigit(vers[1]))) /* Fom Service Pack 4 */
439 return (TRUE); /* same as for W2K */
447 * Universal function to get a file handle to the CD device. Since
448 * NT 4.0 wants just the GENERIC_READ flag, and Win2K wants both
449 * GENERIC_READ and GENERIC_WRITE (why a read-only CD device needs
450 * GENERIC_WRITE access is beyond me...), the easist workaround is to just
454 GetFileHandle(BYTE i, BOOL openshared)
458 DWORD dwFlags = GENERIC_READ;
459 DWORD dwAccessMode = 0;
461 dwAccessMode = FILE_SHARE_READ;
462 if (w2kstyle_create()) { /* if Win2K or greater, add GENERIC_WRITE */
463 dwFlags |= GENERIC_WRITE;
464 dwAccessMode |= FILE_SHARE_WRITE;
466 fprintf(usalp_errfile, "SPTI: GetFileHandle(): Setting for Win2K\n");
469 snprintf(buf, sizeof (buf), "\\\\.\\%c:", (char)('A'+i));
470 #ifdef CREATE_NONSHARED
472 fh = CreateFile(buf, dwFlags, dwAccessMode, NULL,
473 OPEN_EXISTING, 0, NULL);
475 fh = CreateFile(buf, dwFlags, 0, NULL,
476 OPEN_EXISTING, 0, NULL);
478 if (!openshared && fh == INVALID_HANDLE_VALUE && GetLastError() == ERROR_SHARING_VIOLATION)
480 fh = CreateFile(buf, dwFlags, dwAccessMode, NULL,
481 OPEN_EXISTING, 0, NULL);
482 if (fh == INVALID_HANDLE_VALUE) {
484 * it went foobar somewhere, so try it with the GENERIC_WRITE
487 dwFlags ^= GENERIC_WRITE;
488 dwAccessMode ^= FILE_SHARE_WRITE;
489 #ifdef CREATE_NONSHARED
491 fh = CreateFile(buf, dwFlags, dwAccessMode, NULL,
492 OPEN_EXISTING, 0, NULL);
494 fh = CreateFile(buf, dwFlags, 0, NULL,
495 OPEN_EXISTING, 0, NULL);
497 if (!openshared && fh == INVALID_HANDLE_VALUE && GetLastError() == ERROR_SHARING_VIOLATION)
499 fh = CreateFile(buf, dwFlags, dwAccessMode, NULL,
500 OPEN_EXISTING, 0, NULL);
503 if (fh == INVALID_HANDLE_VALUE)
504 fprintf(usalp_errfile, "SPTI: CreateFile() failed! -> %d\n", GetLastError());
506 fprintf(usalp_errfile, "SPTI: CreateFile() returned %d\n", GetLastError());
514 * fills in a pDrive structure with information from a SCSI_INQUIRY
515 * and obtains the ha:tgt:lun values via IOCTL_SCSI_GET_ADDRESS
517 static void GetDriveInformation(BYTE i, DRIVE *pDrive)
521 SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
522 SCSI_ADDRESS scsiAddr;
525 BYTE inqData[NTSCSI_HA_INQUIRY_SIZE];
528 fprintf(usalp_errfile, "SPTI: Checking drive %c:", 'A'+i);
531 fh = GetFileHandle(i, TRUE); /* No NONSHARED Create for inquiry */
533 if (fh == INVALID_HANDLE_VALUE) {
535 fprintf(usalp_errfile, " : fh == INVALID_HANDLE_VALUE\n");
541 fprintf(usalp_errfile, " : Index %d: fh == %08X\n", i, fh);
546 * Get the drive inquiry data
548 memset(&swb, 0, sizeof (swb));
549 memset(inqData, 0, sizeof (inqData));
550 swb.spt.Length = sizeof (SCSI_PASS_THROUGH_DIRECT);
551 swb.spt.CdbLength = 6;
552 swb.spt.SenseInfoLength = 24;
553 swb.spt.DataIn = SCSI_IOCTL_DATA_IN;
554 swb.spt.DataTransferLength = 100;
555 swb.spt.TimeOutValue = 2;
556 swb.spt.DataBuffer = inqData;
557 swb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);
558 swb.spt.Cdb[0] = SCSI_CMD_INQUIRY;
559 swb.spt.Cdb[4] = NTSCSI_HA_INQUIRY_SIZE;
561 length = sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
562 status = DeviceIoControl(fh,
563 IOCTL_SCSI_PASS_THROUGH_DIRECT,
574 fprintf(usalp_errfile, "SPTI: Error DeviceIoControl() -> %d\n", GetLastError());
579 memcpy(pDrive->inqData, inqData, NTSCSI_HA_INQUIRY_SIZE);
582 * get the address (path/tgt/lun) of the drive via IOCTL_SCSI_GET_ADDRESS
584 memset(&scsiAddr, 0, sizeof (SCSI_ADDRESS));
585 scsiAddr.Length = sizeof (SCSI_ADDRESS);
586 if (DeviceIoControl(fh, IOCTL_SCSI_GET_ADDRESS, NULL, 0,
587 &scsiAddr, sizeof (SCSI_ADDRESS), &returned,
590 fprintf(usalp_errfile, "Device %c: Port=%d, PathId=%d, TargetId=%d, Lun=%d\n",
591 (char)i+'A', scsiAddr.PortNumber, scsiAddr.PathId,
592 scsiAddr.TargetId, scsiAddr.Lun);
594 pDrive->bUsed = TRUE;
595 pDrive->ha = scsiAddr.PortNumber; /* preliminary */
596 pDrive->PortNumber = scsiAddr.PortNumber;
597 pDrive->PathId = scsiAddr.PathId;
598 pDrive->tgt = scsiAddr.TargetId;
599 pDrive->lun = scsiAddr.Lun;
600 pDrive->driveLetter = i;
601 pDrive->hDevice = INVALID_HANDLE_VALUE;
603 } else if (GetLastError() == 50) { /* support USB/FIREWIRE devices where this call is not supported assign drive letter as device ID */
604 pDrive->bUsed = TRUE;
606 pDrive->PortNumber = i+64; /* hopefully no conflict with other PortNumber */
610 pDrive->driveLetter = i;
611 pDrive->hDevice = INVALID_HANDLE_VALUE;
613 fprintf(usalp_errfile, "USB/Firewire Device %c: Port=%d, TargetId=%d, Lun=%d\n", (char)i+'A', i, 0, 0);
616 pDrive->bUsed = FALSE;
618 fprintf(usalp_errfile, "SPTI: Device %s: Error DeviceIoControl(): %d\n", (char)i+'A', GetLastError());
624 fprintf(usalp_errfile, "SPTI: Adding drive %c: (%d:%d:%d)\n", 'A'+i,
625 pDrive->ha, pDrive->tgt, pDrive->lun);
633 SPTIHandleHaInquiry(LPSRB_HAInquiry lpsrb)
637 lpsrb->HA_Count = sptiglobal.numAdapters;
638 if (lpsrb->SRB_HaId >= sptiglobal.numAdapters) {
639 lpsrb->SRB_Status = SS_INVALID_HA;
640 return (SS_INVALID_HA);
642 lpsrb->HA_SCSI_ID = 7; /* who cares... we're not really an ASPI manager */
643 memcpy(lpsrb->HA_ManagerId, "AKASPI v0.000001", 16);
644 memcpy(lpsrb->HA_Identifier, "SCSI Adapter ", 16);
645 lpsrb->HA_Identifier[13] = (char)('0'+lpsrb->SRB_HaId);
646 memset(lpsrb->HA_Unique, 0, 16);
647 lpsrb->HA_Unique[3] = 8;
648 pMTL = (LPDWORD)&lpsrb->HA_Unique[4];
651 lpsrb->SRB_Status = SS_COMP;
656 * Looks up the index in the drive array for a given ha:tgt:lun triple
659 SPTIGetDeviceIndex(BYTE ha, BYTE tgt, BYTE lun)
664 fprintf(usalp_errfile, "SPTI: SPTIGetDeviceIndex, %d, %d, %d\n", ha,
668 for (i = NUM_FLOPPY_DRIVES; i < NUM_MAX_NTSCSI_DRIVES; i++) {
669 if (sptiglobal.drive[i].bUsed) {
672 lpd = &sptiglobal.drive[i];
673 if ((lpd->ha == ha) && (lpd->tgt == tgt) && (lpd->lun == lun))
682 * Converts ASPI-style SRB to SCSI Pass Through IOCTL
686 SPTIExecSCSICommand(LPSRB_ExecSCSICmd lpsrb, int sptTimeOutValue, BOOL bBeenHereBefore)
689 SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
695 idx = SPTIGetDeviceIndex(lpsrb->SRB_HaId, lpsrb->SRB_Target, lpsrb->SRB_Lun);
698 lpsrb->SRB_Status = SS_NO_DEVICE;
699 return (SS_NO_DEVICE);
702 if (lpsrb->CDBByte[0] == SCSI_CMD_INQUIRY) {
703 lpsrb->SRB_Status = SS_COMP;
704 memcpy(lpsrb->SRB_BufPointer, sptiglobal.drive[idx].inqData, NTSCSI_HA_INQUIRY_SIZE);
708 if (sptiglobal.drive[idx].hDevice == INVALID_HANDLE_VALUE)
709 sptiglobal.drive[idx].hDevice = GetFileHandle(sptiglobal.drive[idx].driveLetter, FALSE);
711 memset(&swb, 0, sizeof (swb));
712 swb.spt.Length = sizeof (SCSI_PASS_THROUGH);
713 swb.spt.CdbLength = lpsrb->SRB_CDBLen;
714 if (lpsrb->SRB_Flags & SRB_DIR_IN)
715 swb.spt.DataIn = SCSI_IOCTL_DATA_IN;
716 else if (lpsrb->SRB_Flags & SRB_DIR_OUT)
717 swb.spt.DataIn = SCSI_IOCTL_DATA_OUT;
719 swb.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED;
720 swb.spt.DataTransferLength = lpsrb->SRB_BufLen;
721 swb.spt.TimeOutValue = sptTimeOutValue;
722 swb.spt.SenseInfoLength = lpsrb->SRB_SenseLen;
723 swb.spt.DataBuffer = lpsrb->SRB_BufPointer;
724 swb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);
725 memcpy(swb.spt.Cdb, lpsrb->CDBByte, lpsrb->SRB_CDBLen);
726 length = sizeof (swb);
729 fprintf(usalp_errfile, "SPTI: SPTIExecSCSICmd: calling DeviceIoControl()");
730 fprintf(usalp_errfile, " : cmd == 0x%02X", swb.spt.Cdb[0]);
732 status = DeviceIoControl(sptiglobal.drive[idx].hDevice,
733 IOCTL_SCSI_PASS_THROUGH_DIRECT,
741 lpsrb->SRB_SenseLen = swb.spt.SenseInfoLength;
742 memcpy(lpsrb->SenseArea, swb.ucSenseBuf, lpsrb->SRB_SenseLen);
743 if (status && swb.spt.ScsiStatus == 0) {
744 lpsrb->SRB_Status = SS_COMP;
746 fprintf(usalp_errfile, " : SRB_Status == SS_COMP\n");
751 lpsrb->SRB_Status = SS_ERR;
752 /* lpsrb->SRB_TargStat = 0x0004;*/
753 lpsrb->SRB_TargStat = swb.spt.ScsiStatus;
755 dwErrCode = GetLastError();
757 fprintf(usalp_errfile, " : error == %d handle == %08X\n", dwErrCode, sptiglobal.drive[idx].hDevice);
760 * KLUDGE ALERT! KLUDGE ALERT! KLUDGE ALERT!
761 * Whenever a disk changer switches disks, it may render the device
762 * handle invalid. We try to catch these errors here and recover
765 if (!bBeenHereBefore &&
766 ((dwErrCode == ERROR_MEDIA_CHANGED) || (dwErrCode == ERROR_INVALID_HANDLE))) {
767 if (dwErrCode != ERROR_INVALID_HANDLE)
768 CloseHandle(sptiglobal.drive[idx].hDevice);
769 GetDriveInformation(idx, &sptiglobal.drive[idx]);
771 if (sptiglobal.drive[idx].bUsed)
772 for (j = 0; j < sptihamax; j++) {
773 if (sptihasortarr[j] ==
774 ((sptiglobal.drive[idx].PortNumber << 8) | sptiglobal.drive[idx].PathId)) {
775 sptiglobal.drive[idx].ha = j;
781 fprintf(usalp_errfile, "SPTI: SPTIExecSCSICommand: Retrying after ERROR_MEDIA_CHANGED\n");
783 return (SPTIExecSCSICommand(lpsrb, sptTimeOutValue, TRUE));
786 return (lpsrb->SRB_Status);
788 /* SPTI End -----------------------------------------------------------------*/
795 errmsgno(EX_BAD, "Cannot close Win32-ASPI-Driver.\n");
799 * Return version information for the low level SCSI transport code.
800 * This has been introduced to make it easier to trace down problems
804 usalo_version(SCSI *usalp, int what)
806 if (usalp != (SCSI *)0) {
811 return (_usal_itrans_version);
812 return (_usal_trans_version);
814 * If you changed this source, you are not allowed to
815 * return "schily" for the SCG_AUTHOR request.
818 return (_usal_auth_cdrkit);
827 usalo_help(SCSI *usalp, FILE *f)
829 __usal_help(f, "ASPI", "Generic transport independent SCSI",
830 "ASPI:", "bus,target,lun", "ASPI:1,2,0", TRUE, FALSE);
831 __usal_help(f, "SPTI", "Generic SCSI for Windows NT/2000/XP",
832 "SPTI:", "bus,target,lun", "SPTI:1,2,0", TRUE, FALSE);
837 usalo_open(SCSI *usalp, char *device)
839 int busno = usal_scsibus(usalp);
840 int tgt = usal_target(usalp);
841 int tlun = usal_lun(usalp);
843 /*usal_local(usalp)->drive_wanted = NULL;
844 for(i=0;i<MAX_SCG*MAX_TGT*MAX_LUN;i++)
845 usallocal(usalp)->filenames[i]=NULL;
847 usalp->local = calloc(1, sizeof (struct usal_local));
848 if (usalp->local == NULL)
851 if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
854 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
855 "Illegal value for busno, target or lun '%d,%d,%d'",
860 /* Explicite choice of Schilling syntax */
861 if (device != NULL && (strcmp(device, "SPTI") == 0 || strcmp(device, "ASPI") == 0))
864 /* use device as drive letter */
865 if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
869 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
870 "Open by 'devname' not supported on this OS");
875 usallocal(usalp)->drive_wanted = *device;
877 /* not the finest solution but prevents breaking on various
878 * places for no good reasons... */
879 usal_scsibus(usalp)=0;
880 usal_target(usalp)=0;
885 if (DriverLoaded <= 0) { /* do not change access method on open driver */
895 if (usalp->debug > 0) {
896 fprintf((FILE *)usalp->errfile,
897 "usalo_open: Prefered SCSI transport: %s\n",
898 UsingSPTI ? "SPTI":"ASPI");
900 if (device != NULL && strcmp(device, "SPTI") == 0) {
903 } else if (device != NULL && strcmp(device, "ASPI") == 0) {
907 if (device != NULL && usalp->debug > 0) {
908 fprintf((FILE *)usalp->errfile,
909 "usalo_open: Selected SCSI transport: %s\n",
910 UsingSPTI ? "SPTI":"ASPI");
915 * Check if variables are within the range
917 if (tgt >= 0 && tgt >= 0 && tlun >= 0) {
919 * This is the non -scanbus case.
922 } else if (tgt == -2 && tgt == -2 &&
923 (tgt == -2 || tlun >= 0)) {
925 * This is the dev=ASPI case.
928 } else if (tgt != -1 || tgt != -1 || tlun != -1) {
935 * Try to open ASPI-Router
937 if (!open_driver(usalp))
941 * More than we have ...
943 if (busno >= busses) {
949 * Install Exit Function which closes the ASPI-Router
960 usalo_close(SCSI *usalp)
964 for(i=0;i<MAX_SCG*MAX_TGT*MAX_LUN;i++) {
965 if(usallocal(usalp)->filenames[i]) {
966 free(usallocal(usalp)->filenames[i]);
967 usallocal(usalp)->filenames[i]=NULL;
975 //printf("closing\n");
982 usalo_maxdma(SCSI *usalp, long amt)
984 return (MAX_DMA_WNT);
988 usalo_getbuf(SCSI *usalp, long amt)
990 if (usalp->debug > 0) {
991 fprintf((FILE *)usalp->errfile,
992 "usalo_getbuf: %ld bytes\n", amt);
994 usalp->bufbase = malloc((size_t)(amt));
995 return (usalp->bufbase);
999 usalo_freebuf(SCSI *usalp)
1002 free(usalp->bufbase);
1003 usalp->bufbase = NULL;
1007 usalo_havebus(SCSI *usalp, int busno)
1009 if (busno < 0 || busno >= busses)
1016 usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
1018 if (busno < 0 || busno >= busses ||
1019 tgt < 0 || tgt >= MAX_TGT ||
1020 tlun < 0 || tlun >= MAX_LUN)
1031 usalo_initiator_id(SCSI *usalp)
1035 if (ha_inquiry(usalp, usal_scsibus(usalp), &s) < 0)
1037 return (s.HA_SCSI_ID);
1041 usalo_isatapi(SCSI *usalp)
1043 return (-1); /* XXX Need to add real test */
1048 * XXX usalo_reset not yet tested
1051 usalo_reset(SCSI *usalp, int what)
1055 DWORD EventStatus = WAIT_OBJECT_0;
1056 HANDLE Event = NULL;
1057 SRB_BusDeviceReset s;
1059 if (what == SCG_RESET_NOP) {
1063 return (0); /* Can ASPI really reset? */
1065 if (what != SCG_RESET_BUS) {
1070 fprintf((FILE *)usalp->errfile,
1071 "Reset SCSI device not implemented with SPTI\n");
1076 * XXX Does this reset TGT or BUS ???
1078 if (usalp->debug > 0) {
1079 fprintf((FILE *)usalp->errfile,
1080 "Attempting to reset SCSI device\n");
1084 * Check if ASPI library is loaded
1086 if (DriverLoaded <= 0) {
1087 fprintf((FILE *)usalp->errfile,
1088 "error in usalo_reset: ASPI driver not loaded !\n");
1092 memset(&s, 0, sizeof (s)); /* Clear SRB_BesDeviceReset structure */
1094 Event = CreateEvent(NULL, TRUE, FALSE, NULL);
1097 * Set structure variables
1099 s.SRB_Cmd = SC_RESET_DEV; /* ASPI command code = SC_RESET_DEV */
1100 s.SRB_HaId = usal_scsibus(usalp); /* ASPI host adapter number */
1101 s.SRB_Flags = SRB_EVENT_NOTIFY; /* Flags */
1102 s.SRB_Target = usal_target(usalp); /* Target's SCSI ID */
1103 s.SRB_Lun = usal_lun(usalp); /* Target's LUN number */
1104 s.SRB_PostProc = (LPVOID)Event; /* Post routine */
1107 * Initiate SCSI command
1109 Status = pfnSendASPI32Command((LPSRB)&s);
1114 if (Status == SS_PENDING) {
1116 * Wait till command completes
1118 EventStatus = WaitForSingleObject(Event, INFINITE);
1122 /**************************************************/
1123 /* Reset event to non-signaled state. */
1124 /**************************************************/
1126 if (EventStatus == WAIT_OBJECT_0) {
1134 * Close the event handle
1141 if (s.SRB_Status != SS_COMP) {
1142 fprintf((FILE *)usalp->errfile,
1143 "ERROR! 0x%08X\n", s.SRB_Status);
1146 * Indicate that error has occured
1151 if (usalp->debug > 0) {
1152 fprintf((FILE *)usalp->errfile,
1153 "Reset SCSI device completed\n");
1157 * Everything went OK
1163 #ifdef DEBUG_WNTASPI
1165 DebugScsiSend(SCSI *usalp, SRB_ExecSCSICmd *s, int bDisplayBuffer)
1169 fprintf((FILE *)usalp->errfile, "\n\nDebugScsiSend\n");
1170 fprintf((FILE *)usalp->errfile, "s->SRB_Cmd = 0x%02x\n", s->SRB_Cmd);
1171 fprintf((FILE *)usalp->errfile, "s->SRB_HaId = 0x%02x\n", s->SRB_HaId);
1172 fprintf((FILE *)usalp->errfile, "s->SRB_Flags = 0x%02x\n", s->SRB_Flags);
1173 fprintf((FILE *)usalp->errfile, "s->SRB_Target = 0x%02x\n", s->SRB_Target);
1174 fprintf((FILE *)usalp->errfile, "s->SRB_Lun = 0x%02x\n", s->SRB_Lun);
1175 fprintf((FILE *)usalp->errfile, "s->SRB_BufLen = 0x%02x\n", s->SRB_BufLen);
1176 fprintf((FILE *)usalp->errfile, "s->SRB_BufPointer = %x\n", s->SRB_BufPointer);
1177 fprintf((FILE *)usalp->errfile, "s->SRB_CDBLen = 0x%02x\n", s->SRB_CDBLen);
1178 fprintf((FILE *)usalp->errfile, "s->SRB_SenseLen = 0x%02x\n", s->SRB_SenseLen);
1179 fprintf((FILE *)usalp->errfile, "s->CDBByte =");
1180 for (i = 0; i < min(s->SRB_CDBLen, 16); i++) {
1181 fprintf((FILE *)usalp->errfile, " %02X ", s->CDBByte[i]);
1183 fprintf((FILE *)usalp->errfile, "\n");
1186 if (bDisplayBuffer != 0 && s->SRB_BufLen >= 8) {
1188 fprintf((FILE *)usalp->errfile, "s->SRB_BufPointer =");
1189 for (i = 0; i < 8; i++) {
1190 fprintf((FILE *)usalp->errfile,
1191 " %02X ", ((char *)s->SRB_BufPointer)[i]);
1193 fprintf((FILE *)usalp->errfile, "\n");
1196 fprintf((FILE *)usalp->errfile, "Debug done\n");
1201 copy_sensedata(SRB_ExecSCSICmd *cp, struct usal_cmd *sp)
1203 sp->sense_count = cp->SRB_SenseLen;
1204 if (sp->sense_count > sp->sense_len)
1205 sp->sense_count = sp->sense_len;
1207 memset(&sp->u_sense.Sense, 0x00, sizeof (sp->u_sense.Sense));
1208 memcpy(&sp->u_sense.Sense, cp->SenseArea, sp->sense_count);
1210 sp->u_scb.cmd_scb[0] = cp->SRB_TargStat;
1217 set_error(SRB_ExecSCSICmd *cp, struct usal_cmd *sp)
1219 switch (cp->SRB_Status) {
1221 case SS_COMP: /* 0x01 SRB completed without error */
1222 sp->error = SCG_NO_ERROR;
1226 case SS_ERR: /* 0x04 SRB completed with error */
1228 * If the SCSI Status byte is != 0, we definitely could send
1229 * the command to the target. We signal NO transport error.
1231 sp->error = SCG_NO_ERROR;
1233 if (cp->SRB_TargStat)
1236 case SS_PENDING: /* 0x00 SRB being processed */
1238 * XXX Could SS_PENDING happen ???
1240 case SS_ABORTED: /* 0x02 SRB aborted */
1241 case SS_ABORT_FAIL: /* 0x03 Unable to abort SRB */
1243 sp->error = SCG_RETRYABLE;
1247 case SS_INVALID_CMD: /* 0x80 Invalid ASPI command */
1248 case SS_INVALID_HA: /* 0x81 Invalid host adapter number */
1249 case SS_NO_DEVICE: /* 0x82 SCSI device not installed */
1251 case SS_INVALID_SRB: /* 0xE0 Invalid parameter set in SRB */
1252 case SS_ILLEGAL_MODE: /* 0xE2 Unsupported Windows mode */
1253 case SS_NO_ASPI: /* 0xE3 No ASPI managers */
1254 case SS_FAILED_INIT: /* 0xE4 ASPI for windows failed init */
1255 case SS_MISMATCHED_COMPONENTS: /* 0xE7 The DLLs/EXEs of ASPI don't */
1257 case SS_NO_ADAPTERS: /* 0xE8 No host adapters to manager */
1259 case SS_ASPI_IS_SHUTDOWN: /* 0xEA Call came to ASPI after */
1260 /* PROCESS_DETACH */
1261 case SS_BAD_INSTALL: /* 0xEB The DLL or other components */
1262 /* are installed wrong */
1263 sp->error = SCG_FATAL;
1264 sp->ux_errno = EINVAL;
1268 case SS_OLD_MANAGER: /* 0xE1 ASPI manager doesn't support */
1271 case SS_BUFFER_ALIGN: /* 0xE1 Buffer not aligned (replaces */
1272 /* SS_OLD_MANAGER in Win32) */
1273 sp->error = SCG_FATAL;
1274 sp->ux_errno = EFAULT;
1277 case SS_ASPI_IS_BUSY: /* 0xE5 No resources available to */
1278 /* execute command */
1279 sp->error = SCG_RETRYABLE;
1280 sp->ux_errno = EBUSY;
1284 case SS_BUFFER_TO_BIG: /* 0xE6 Buffer size too big to handle*/
1286 case SS_BUFFER_TOO_BIG: /* 0xE6 Correct spelling of 'too' */
1287 case SS_INSUFFICIENT_RESOURCES: /* 0xE9 Couldn't allocate resources */
1288 /* needed to init */
1289 sp->error = SCG_RETRYABLE;
1290 sp->ux_errno = ENOMEM;
1302 usalo_send(SCSI *usalp)
1304 struct usal_cmd *sp = usalp->scmd;
1306 DWORD EventStatus = WAIT_OBJECT_0;
1307 HANDLE Event = NULL;
1314 * Check if ASPI library is loaded
1316 if (DriverLoaded <= 0) {
1317 errmsgno(EX_BAD, "error in usalo_send: ASPI driver not loaded.\n");
1318 sp->error = SCG_FATAL;
1322 if (usalp->fd < 0) {
1323 sp->error = SCG_FATAL;
1328 * Initialize variables
1330 sp->error = SCG_NO_ERROR;
1331 sp->sense_count = 0;
1332 sp->u_scb.cmd_scb[0] = 0;
1335 memset(&ac, 0, sizeof (ac)); /* Clear SRB structure */
1338 * Check cbd_len > the maximum command pakket that can be handled by ASPI
1340 if (sp->cdb_len > 16) {
1341 sp->error = SCG_FATAL;
1342 sp->ux_errno = EINVAL;
1343 fprintf((FILE *)usalp->errfile,
1344 "sp->cdb_len > sizeof (SRB_ExecSCSICmd.CDBByte). Fatal error in usalo_send, exiting...\n");
1348 * copy cdrecord command into SRB
1350 movebytes(&sp->cdb, &(s->CDBByte), sp->cdb_len);
1352 Event = CreateEvent(NULL, TRUE, FALSE, NULL);
1355 * Fill ASPI structure
1357 s->SRB_Cmd = SC_EXEC_SCSI_CMD; /* SCSI Command */
1358 s->SRB_HaId = usal_scsibus(usalp); /* Host adapter number */
1359 s->SRB_Flags = SRB_EVENT_NOTIFY; /* Flags */
1360 s->SRB_Target = usal_target(usalp); /* Target SCSI ID */
1361 s->SRB_Lun = usal_lun(usalp); /* Target SCSI LUN */
1362 s->SRB_BufLen = sp->size; /* # of bytes transferred */
1363 s->SRB_BufPointer = sp->addr; /* pointer to data buffer */
1364 s->SRB_CDBLen = sp->cdb_len; /* SCSI command length */
1365 s->SRB_PostProc = Event; /* Post proc event */
1367 s->SRB_SenseLen = SENSE_LEN_SPTI; /* Length of sense buffer, SPTI returns SenseInfoLength */
1369 s->SRB_SenseLen = SENSE_LEN; /* fixed length 14 for ASPI */
1371 * Do we receive data from this ASPI command?
1373 if (sp->flags & SCG_RECV_DATA) {
1375 s->SRB_Flags |= SRB_DIR_IN;
1378 * Set direction to output
1381 s->SRB_Flags |= SRB_DIR_OUT;
1385 #ifdef DEBUG_WNTASPI
1387 * Dump some debug information when enabled
1389 DebugScsiSend(usalp, s, TRUE);
1390 /* DebugScsiSend(usalp, s, (s->SRB_Flags&SRB_DIR_OUT) == SRB_DIR_OUT);*/
1394 * ------------ Send SCSI command --------------------------
1397 ResetEvent(Event); /* Clear event handle */
1399 #ifdef _DEBUG_SCSIPT
1400 usalp_errfile = (FILE *)usalp->errfile;
1402 Status = SPTIExecSCSICommand(s, sp->timeout, FALSE);
1405 Status = pfnSendASPI32Command((LPSRB)s); /* Initiate SCSI command */
1406 if (Status == SS_PENDING) { /* If in progress */
1408 * Wait untill command completes, or times out.
1410 EventStatus = WaitForSingleObject(Event, sp->timeout*1000L);
1411 /* EventStatus = WaitForSingleObject(Event, 10L);*/
1413 if (EventStatus == WAIT_OBJECT_0)
1414 ResetEvent(Event); /* Clear event, time out */
1416 if (s->SRB_Status == SS_PENDING) { /* Check if we got a timeout */
1417 if (usalp->debug > 0) {
1418 fprintf((FILE *)usalp->errfile,
1421 scsiabort(usalp, s);
1422 ResetEvent(Event); /* Clear event, time out */
1423 CloseHandle(Event); /* Close the event handle */
1425 sp->error = SCG_TIMEOUT;
1426 return (1); /* Return error */
1429 CloseHandle(Event); /* Close the event handle */
1432 * Check ASPI command status
1434 if (s->SRB_Status != SS_COMP) {
1435 if (usalp->debug > 0) {
1436 fprintf((FILE *)usalp->errfile,
1437 "Error in usalo_send: s->SRB_Status is 0x%x\n", s->SRB_Status);
1440 set_error(s, sp); /* Set error flags */
1441 copy_sensedata(s, sp); /* Copy sense and status */
1443 if (usalp->debug > 0) {
1444 fprintf((FILE *)usalp->errfile,
1445 "Mapped to: error %d errno: %d\n", sp->error, sp->ux_errno);
1456 /***************************************************************************
1458 * BOOL open_driver() *
1460 * Opens the ASPI Router device driver and sets device_handle. *
1463 * FALSE - Unsuccessful opening of device driver *
1465 * Preconditions: ASPI Router driver has be loaded *
1467 ***************************************************************************/
1469 open_driver(SCSI *usalp)
1476 #ifdef DEBUG_WNTASPI
1477 fprintf((FILE *)usalp->errfile, "enter open_driver\n");
1481 * Check if ASPI library is already loaded yet
1483 if (DriverLoaded > 0) {
1489 * Load the ASPI library or SPTI
1491 #ifdef _DEBUG_SCSIPT
1492 usalp_errfile = (FILE *)usalp->errfile;
1496 if (InitSCSIPT(usalp) > 0) DriverLoaded++;
1499 if ((!UsingSPTI || !ForceAccess) && DriverLoaded <= 0) {
1501 if (!UsingSPTI || !ForceAccess) {
1503 if (load_aspi(usalp)) {
1510 if ((UsingSPTI || !ForceAccess) && DriverLoaded <= 0)
1511 if (InitSCSIPT(usalp) > 0)
1513 #endif /*PREFER_SPTI*/
1515 if (DriverLoaded <= 0) {
1520 fprintf((FILE *)usalp->errfile, "Can not load %s driver! ",
1521 UsingSPTI ? "SPTI":"ASPI");
1526 if (usalp->debug > 0)
1527 fprintf((FILE *)usalp->errfile, "using SPTI Transport\n");
1529 if (!sptiglobal.numAdapters)
1530 astatus = (DWORD)(MAKEWORD(0, SS_NO_ADAPTERS));
1532 astatus = (DWORD)(MAKEWORD(sptiglobal.numAdapters, SS_COMP));
1534 astatus = pfnGetASPI32SupportInfo();
1537 ASPIStatus = HIBYTE(LOWORD(astatus));
1538 HACount = LOBYTE(LOWORD(astatus));
1540 if (usalp->debug > 0) {
1541 fprintf((FILE *)usalp->errfile,
1542 "open_driver %lX HostASPIStatus=0x%x HACount=0x%x\n", astatus, ASPIStatus, HACount);
1545 if (ASPIStatus != SS_COMP && ASPIStatus != SS_NO_ADAPTERS) {
1546 fprintf((FILE *)usalp->errfile, "Could not find any host adapters\n");
1547 fprintf((FILE *)usalp->errfile, "ASPIStatus == 0x%02X", ASPIStatus);
1552 #ifdef DEBUG_WNTASPI
1553 fprintf((FILE *)usalp->errfile, "open_driver HostASPIStatus=0x%x HACount=0x%x\n", ASPIStatus, HACount);
1554 fprintf((FILE *)usalp->errfile, "leaving open_driver\n");
1557 for (i = 0; i < busses; i++) {
1560 ha_inquiry(usalp, i, &s);
1564 * Indicate that library loaded/initialized properly
1570 load_aspi(SCSI *usalp)
1573 hAspiLib = dlopen("WNASPI32", RTLD_NOW);
1575 hAspiLib = LoadLibrary("WNASPI32");
1578 * Check if ASPI library is loaded correctly
1580 if (hAspiLib == NULL) {
1581 #ifdef not_done_later
1582 fprintf((FILE *)usalp->errfile, "Can not load ASPI driver! ");
1588 * Get a pointer to GetASPI32SupportInfo function
1589 * and a pointer to SendASPI32Command function
1592 pfnGetASPI32SupportInfo = (DWORD(*)(void))dlsym(hAspiLib, "GetASPI32SupportInfo");
1593 pfnSendASPI32Command = (DWORD(*)(LPSRB))dlsym(hAspiLib, "SendASPI32Command");
1595 pfnGetASPI32SupportInfo = (DWORD(*)(void))GetProcAddress(hAspiLib, "GetASPI32SupportInfo");
1596 pfnSendASPI32Command = (DWORD(*)(LPSRB))GetProcAddress(hAspiLib, "SendASPI32Command");
1599 if ((pfnGetASPI32SupportInfo == NULL) || (pfnSendASPI32Command == NULL)) {
1600 fprintf((FILE *)usalp->errfile,
1601 "ASPI function not found in library! ");
1606 * The following functions are currently not used by libusal.
1607 * If we start to use them, we need to check whether the founctions
1608 * could be found in the ASPI library that just has been loaded.
1611 pfnGetASPI32Buffer = (BOOL(*)(PASPI32BUFF))dlsym(hAspiLib, "GetASPI32Buffer");
1612 pfnFreeASPI32Buffer = (BOOL(*)(PASPI32BUFF))dlsym(hAspiLib, "FreeASPI32Buffer");
1613 pfnTranslateASPI32Address = (BOOL(*)(PDWORD, PDWORD))dlsym(hAspiLib, "TranslateASPI32Address");
1615 pfnGetASPI32Buffer = (BOOL(*)(PASPI32BUFF))GetProcAddress(hAspiLib, "GetASPI32Buffer");
1616 pfnFreeASPI32Buffer = (BOOL(*)(PASPI32BUFF))GetProcAddress(hAspiLib, "FreeASPI32Buffer");
1617 pfnTranslateASPI32Address = (BOOL(*)(PDWORD, PDWORD))GetProcAddress(hAspiLib, "TranslateASPI32Address");
1622 /***************************************************************************
1624 * BOOL close_driver() *
1626 * Closes the device driver *
1629 * FALSE - Unsuccessful closing of device driver *
1631 * Preconditions: ASPI Router driver has be opened with open_driver *
1633 ***************************************************************************/
1637 if (--DriverLoaded > 0)
1640 * If library is loaded
1644 * Clear all variables
1647 pfnGetASPI32SupportInfo = NULL;
1648 pfnSendASPI32Command = NULL;
1649 pfnGetASPI32Buffer = NULL;
1650 pfnFreeASPI32Buffer = NULL;
1651 pfnTranslateASPI32Address = NULL;
1654 * Free ASPI library, we do not need it any longer
1659 FreeLibrary(hAspiLib);
1665 * Indicate that shutdown has been finished properly
1671 ha_inquiry(SCSI *usalp, int id, SRB_HAInquiry *ip)
1675 ip->SRB_Cmd = SC_HA_INQUIRY;
1678 ip->SRB_Hdr_Rsvd = 0;
1681 Status = SPTIHandleHaInquiry(ip);
1683 Status = pfnSendASPI32Command((LPSRB)ip);
1685 if (usalp->debug > 0) {
1686 fprintf((FILE *)usalp->errfile, "Status : %ld\n", Status);
1687 fprintf((FILE *)usalp->errfile, "hacount: %d\n", ip->HA_Count);
1688 fprintf((FILE *)usalp->errfile, "SCSI id: %d\n", ip->HA_SCSI_ID);
1689 fprintf((FILE *)usalp->errfile, "Manager: '%.16s'\n", ip->HA_ManagerId);
1690 fprintf((FILE *)usalp->errfile, "Identif: '%.16s'\n", ip->HA_Identifier);
1691 usal_prbytes("Unique:", ip->HA_Unique, 16);
1693 if (ip->SRB_Status != SS_COMP)
1700 resetSCSIBus(SCSI *usalp)
1704 SRB_BusDeviceReset s;
1707 fprintf((FILE *)usalp->errfile,
1708 "Reset SCSI bus not implemented with SPTI\n");
1712 fprintf((FILE *)usalp->errfile, "Attempting to reset SCSI bus\n");
1714 Event = CreateEvent(NULL, TRUE, FALSE, NULL);
1716 memset(&s, 0, sizeof (s)); /* Clear SRB_BesDeviceReset structure */
1719 * Set structure variables
1721 s.SRB_Cmd = SC_RESET_DEV;
1722 s.SRB_PostProc = (LPVOID)Event;
1730 * Initiate SCSI command
1732 Status = pfnSendASPI32Command((LPSRB)&s);
1737 if (Status == SS_PENDING) {
1739 * Wait till command completes
1741 WaitForSingleObject(Event, INFINITE);
1745 * Close the event handle
1752 if (s.SRB_Status != SS_COMP) {
1753 fprintf((FILE *)usalp->errfile, "ERROR 0x%08X\n", s.SRB_Status);
1756 * Indicate that error has occured
1762 * Everything went OK
1766 #endif /* __USED__ */
1769 scsiabort(SCSI *usalp, SRB_ExecSCSICmd *sp)
1775 fprintf((FILE *)usalp->errfile,
1776 "Abort SCSI not implemented with SPTI\n");
1780 if (usalp->debug > 0) {
1781 fprintf((FILE *)usalp->errfile,
1782 "Attempting to abort SCSI command\n");
1786 * Check if ASPI library is loaded
1788 if (DriverLoaded <= 0) {
1789 fprintf((FILE *)usalp->errfile,
1790 "error in scsiabort: ASPI driver not loaded !\n");
1795 * Set structure variables
1797 s.SRB_Cmd = SC_ABORT_SRB; /* ASPI command code = SC_ABORT_SRB */
1798 s.SRB_HaId = usal_scsibus(usalp); /* ASPI host adapter number */
1799 s.SRB_Flags = 0; /* Flags */
1800 s.SRB_ToAbort = (LPSRB)&sp; /* sp */
1803 * Initiate SCSI abort
1805 Status = pfnSendASPI32Command((LPSRB)&s);
1810 if (s.SRB_Status != SS_COMP) {
1811 fprintf((FILE *)usalp->errfile, "Abort ERROR! 0x%08X\n", s.SRB_Status);
1814 * Indicate that error has occured
1819 if (usalp->debug > 0)
1820 fprintf((FILE *)usalp->errfile, "Abort SCSI command completed\n");
1823 * Everything went OK
1829 #define HAVE_NAT_NAMES
1830 static char * usalo_natname(SCSI *usalp, int busno, int tgt, int tlun) {
1832 static char name[3];
1833 printf("hm, %d, %d, %d\n", busno, tgt, tlun);
1834 if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN)
1836 for (i = NUM_FLOPPY_DRIVES; i < NUM_MAX_NTSCSI_DRIVES; i++) {
1837 if(sptiglobal.drive[i].bUsed &&
1838 tlun == sptiglobal.drive[i].lun &&
1839 tgt == sptiglobal.drive[i].tgt &&
1840 busno == sptiglobal.drive[i].ha)
1842 snprintf(name, 3, "%c:", 'A'+sptiglobal.drive[i].driveLetter);