forgot to attach the files :(
/* * DDK definitions for scsi media access * * Copyright (C) 2002 Laurent Pinchart * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef _NTDDSCSI_H_ #define _NTDDSCSI_H_ #ifdef __cplusplus extern "C" { #endif #define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER #define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) #define IOCTL_SCSI_MINIPORT CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) #define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE(IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) #define IOCTL_SCSI_GET_ADDRESS CTL_CODE(IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_SCSI_RESCAN_BUS CTL_CODE(IOCTL_SCSI_BASE, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_SCSI_GET_DUMP_POINTERS CTL_CODE(IOCTL_SCSI_BASE, 0x0408, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_SCSI_FREE_DUMP_POINTERS CTL_CODE(IOCTL_SCSI_BASE, 0x0409, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_IDE_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x040a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) #define SCSI_IOCTL_DATA_OUT 0 #define SCSI_IOCTL_DATA_IN 1 #define SCSI_IOCTL_DATA_UNSPECIFIED 2 typedef struct _SCSI_PASS_THROUGH { USHORT Length; UCHAR ScsiStatus; UCHAR PathId; UCHAR TargetId; UCHAR Lun; UCHAR CdbLength; UCHAR SenseInfoLength; UCHAR DataIn; ULONG DataTransferLength; ULONG TimeOutValue; ULONG_PTR DataBufferOffset; ULONG SenseInfoOffset; UCHAR Cdb[16]; } SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; typedef struct _SCSI_PASS_THROUGH_DIRECT { USHORT Length; UCHAR ScsiStatus; UCHAR PathId; UCHAR TargetId; UCHAR Lun; UCHAR CdbLength; UCHAR SenseInfoLength; UCHAR DataIn; ULONG DataTransferLength; ULONG TimeOutValue; PVOID DataBuffer; ULONG SenseInfoOffset; UCHAR Cdb[16]; } SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; typedef struct _SCSI_ADDRESS { ULONG Length; UCHAR PortNumber; UCHAR PathId; UCHAR TargetId; UCHAR Lun; } SCSI_ADDRESS, *PSCSI_ADDRESS; #ifdef __cplusplus } #endif #endif /* _NTDDSCSI_H_ */
Index: dlls/ntdll/cdrom.c =================================================================== RCS file: /home/wine/wine/dlls/ntdll/cdrom.c,v retrieving revision 1.7 diff -u -u -r1.7 cdrom.c --- dlls/ntdll/cdrom.c 2 Apr 2002 19:19:49 -0000 1.7 +++ dlls/ntdll/cdrom.c 17 Apr 2002 23:20:41 -0000 @@ -25,16 +25,24 @@ #include <errno.h> #include <string.h> #include <unistd.h> +#include <stdio.h> #include <fcntl.h> #include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> #include "ntddk.h" #include "winioctl.h" #include "ntddstor.h" #include "ntddcdrm.h" +#include "ntddscsi.h" #include "drive.h" #include "file.h" #include "wine/debug.h" +#include "winreg.h" +#include <scsi/sg.h> +#include <linux/major.h> +#include <linux/hdreg.h> #ifdef HAVE_LINUX_CDROM_H # include <linux/cdrom.h> #endif @@ -57,6 +65,125 @@ static struct cdrom_cache cdrom_cache[26]; /****************************************************************** + * CDROM_GetIdeInterface + * + * Determines the ide interface (the number after the ide), and the + * number of the device on that interface for ide cdroms. + * Returns false if the info could not be get + * + * NOTE: this function is used in CDROM_InitRegistry and CDROM_GetAddress + */ + static int CDROM_GetIdeInterface(int dev, int* iface, int* device) { +#if defined(linux) + { + struct stat st; + if (ioctl(dev, SG_EMULATED_HOST) != -1) { + FIXME("not implemented for true scsi drives\n"); + return 0; + } + if ( fstat(dev, &st) == -1 || ! S_ISBLK(st.st_mode)) { + FIXME("cdrom not a block device!!!\n"); + return 0; + } + switch (major(st.st_rdev)) { + case IDE0_MAJOR: *iface = 0; break; + case IDE1_MAJOR: *iface = 1; break; + case IDE2_MAJOR: *iface = 2; break; + case IDE3_MAJOR: *iface = 3; break; + case IDE4_MAJOR: *iface = 4; break; + case IDE5_MAJOR: *iface = 5; break; + case IDE6_MAJOR: *iface = 6; break; + case IDE7_MAJOR: *iface = 7; break; + default: + FIXME("major %d not supported\n", major(st.st_rdev)); + } + *device = (minor(st.st_rdev) == 63 ? 1 : 0); + return 1; + } +#elif defined(__FreeBSD__) || defined(__NetBSD__) + FIXME("not implemented for BSD\n"); + return 0; +#else + FIXME("not implemented for nonlinux\n"); + return 0; +#endif + } + +/****************************************************************** + * CDROM_InitRegistry + * + * Initializes registry to contain scsi info about the cdrom in NT. + * All devices (even not real scsi ones) have this info in NT. + * TODO: for now it only works for non scsi devices + * NOTE: programs usually read these registry entries after sending the + * IOCTL_SCSI_GET_ADDRESS ioctl to the cdrom + */ +static void CDROM_InitRegistry(int dev) { + int portnum, targetid; + int dma; + char buffer[40]; + DWORD value; + HKEY scsiKey; + HKEY portKey; + HKEY busKey; + HKEY targetKey; + + if ( ! CDROM_GetIdeInterface(dev, &portnum, &targetid)) + return; + + /* Ensure there is Scsi key */ + if (RegCreateKeyA(HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\Scsi", &scsiKey)) { + ERR("Cannot create DEVICEMAP\\Scsi registry key\n" ); + return; + } + + snprintf(buffer,40,"Scsi Port %d",portnum); + if (RegCreateKeyA( scsiKey, buffer, &portKey)) { + ERR("Cannot create DEVICEMAP\\Scsi Port registry key\n" ); + return; + } + + RegSetValueExA( portKey,"Driver", 0, REG_SZ, "atapi", strlen("atapi")); + value = 10; + RegSetValueExA( portKey,"FirstBusTimeScanInMs", 0, REG_DWORD, (char*)&value, sizeof(value)); + value = 0; + if (ioctl(dev,HDIO_GET_DMA, &dma) != -1) { + value = dma; + TRACE("setting dma to %lx\n", value); + } + RegSetValueExA( portKey,"DMAEnabled", 0, REG_DWORD, (char*)&value, sizeof(value)); + + if (RegCreateKeyA( portKey, "Scsi Bus 0", &busKey)) { + ERR("Cannot create DEVICEMAP\\Scsi Port\\Scsi Bus registry key\n" ); + return; + } + + if (RegCreateKeyA( busKey, "Initiator Id 255", &targetKey)) { + ERR("Cannot create DEVICEMAP\\Scsi Port\\Scsi Bus\\Initiator Id 255 registry key\n" ); + return; + } + RegCloseKey( targetKey ); + + snprintf(buffer,40,"Target Id %d", targetid); + if (RegCreateKeyA( busKey, buffer, &targetKey)) { + ERR("Cannot create DEVICEMAP\\Scsi Port\\Scsi Bus 0\\Target Id registry key\n" ); + return; + } + + RegSetValueExA( targetKey,"Type", 0, REG_SZ, "CdRomPeripheral", strlen("CdRomPeripheral")); + /* FIXME - maybe real identifier?? */ + RegSetValueExA( targetKey,"Identifier", 0, REG_SZ, "Wine CDROM", strlen("Wine CDROM")); + /* FIXME - we always use Cdrom0 - do not know about the nt behaviour */ + RegSetValueExA( targetKey,"DeviceName", 0, REG_SZ, "Cdrom0", strlen("Cdrom0")); + + RegCloseKey( targetKey ); + RegCloseKey( busKey ); + RegCloseKey( portKey ); + RegCloseKey( scsiKey ); +} + + +/****************************************************************** * CDROM_Open * * @@ -80,6 +207,7 @@ FIXME("Can't open %s: %s\n", root, strerror(errno)); return -1; } + CDROM_InitRegistry(cdrom_cache[dev].fd); } cdrom_cache[dev].count++; return cdrom_cache[dev].fd; @@ -830,6 +958,41 @@ } /****************************************************************** + * CDROM_GetAddress + * + * implements IOCTL_SCSI_GET_ADDRESS + */ +static DWORD CDROM_GetAddress(int dev, SCSI_ADDRESS* address) +{ + int portnum, targetid; + + address->Length = sizeof(SCSI_ADDRESS); + address->PathId = 0; /* bus number */ + address->Lun = 0; + if ( ! CDROM_GetIdeInterface(dev, &portnum, &targetid)) + return STATUS_NOT_SUPPORTED; + + address->PortNumber = portnum; + address->TargetId = targetid; + return 0; +} + +/****************************************************************** + * CDROM_ScsiPassThroughDirect + * + * implements IOCTL_SCSI_PASS_THROUGH_DIRECT + */ +static DWORD CDROM_ScsiPassThroughDirect(int dev, SCSI_PASS_THROUGH_DIRECT* in, SCSI_PASS_THROUGH_DIRECT* out, DWORD len, DWORD* sz) +{ + FIXME("(%d, %lx, %lx, %ld, %lx) stub\n", dev, (DWORD)in, (DWORD)out, len, (DWORD)sz); + TRACE("in data: Length: %d, SenseInfoLength: %d, CdbLength: %d, DataTransferLength %ld" + "DataBuffer: %lx\n", + in->Length, in->SenseInfoLength,in->CdbLength, in->DataTransferLength, + (DWORD)in->DataBuffer); + return STATUS_NOT_SUPPORTED; +} + +/****************************************************************** * CDROM_DeviceIoControl * * @@ -892,6 +1055,7 @@ else error = CDROM_SetTray(dev, TRUE); break; + case IOCTL_CDROM_MEDIA_REMOVAL: case IOCTL_DISK_MEDIA_REMOVAL: case IOCTL_STORAGE_MEDIA_REMOVAL: case IOCTL_STORAGE_EJECTION_CONTROL: @@ -1008,6 +1172,20 @@ else if (lpOutBuffer == NULL) error = STATUS_BUFFER_TOO_SMALL; else error = CDROM_RawRead(dev, (const RAW_READ_INFO*)lpInBuffer, lpOutBuffer, nOutBufferSize, &sz); + break; + case IOCTL_SCSI_GET_ADDRESS: + sz = sizeof(SCSI_ADDRESS); + if (lpInBuffer != NULL || nInBufferSize != 0) error = STATUS_INVALID_PARAMETER; + else if (nOutBufferSize < sz) error = STATUS_BUFFER_TOO_SMALL; + else error = CDROM_GetAddress(dev, (SCSI_ADDRESS*)lpOutBuffer); + break; + case IOCTL_SCSI_PASS_THROUGH_DIRECT: + sz = sizeof(SCSI_PASS_THROUGH_DIRECT); + if (lpInBuffer == NULL || nInBufferSize < sz) + error = STATUS_INVALID_PARAMETER; + else if (lpOutBuffer == NULL || nOutBufferSize < sz) error = STATUS_BUFFER_TOO_SMALL; + else error = CDROM_ScsiPassThroughDirect(dev,(SCSI_PASS_THROUGH_DIRECT*)lpInBuffer, + (SCSI_PASS_THROUGH_DIRECT*)lpOutBuffer, nOutBufferSize, &sz); break; default: FIXME("Unsupported IOCTL %lx\n", dwIoControlCode);