It has more than one Logical Unit Number in the actual device. How do I get
the LUN from the Irp or SCSI Address so I can load it into the CDB ?
Thanks
--
Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply
"Mike Fochtman" <MikeFo...@discussions.microsoft.com> wrote in message
news:DDD265C2-257E-4124...@microsoft.com...
> __________ Information from ESET NOD32 Antivirus, version of virus
> signature database 4682 (20091212) __________
>
> The message was checked by ESET NOD32 Antivirus.
>
> http://www.eset.com
>
>
>
__________ Information from ESET NOD32 Antivirus, version of virus signature database 4682 (20091212) __________
The message was checked by ESET NOD32 Antivirus.
Each LUN will have its own driver installed.
--
Maxim S. Shatskih
Windows DDK MVP
ma...@storagecraft.com
http://www.storagecraft.com
But on subsequent read/writes, I have to somehow find the appropriate LUN
from the Irp so I can set that part of the CDB.
My device uses 6-byte CDB's for everything, so I had to re-write the
xferpkt.c routines in classpnp. But the original version didn't seem to
setup the LogicalUnitNumber member of the CDB. So right now, all the SCSI
CDB packets going to my device on the SCSI bus itself have LUN of zero, even
though I used CreateFile() on any of the device names created by the eight
calls to 'AddDevice()' (one for each LUN of the device).
I tried setting the pCdb->CDB6GENERIC.LogicalUnitNumber = Pkt->Srb.Lun in
the routine SetupReadWriteTransferPacket(), but apparently the Srb.Lun isn't
set at that point as I'm still getting SCSI CDB blocks on the SCSI bus with
LUN=0.
So I still have to 'find' the SCSI address for each incoming IRP so I can
differentiate what i/o requests are for each LUN in the device.
Any other thoughts?
"Maxim S. Shatskih" wrote:
> .
>
As you suggested, I searched through for IOCTL_SCSI_GET_ADDRES and only
found a call to ClassSendDeviceIoControlSynchronous().
I think if I used that I would have to send an IOCTL to the device and
that's sort of the problem, I don't know the LUN for the channel within the
device that I'm trying to talk to.
Isn't this handled by the enumerator for the bus? Seems the SCSI port
driver enumerates all the TargetID/LUN on the bus and calls the appropriate
driver's AddDevice() routine for everything it finds. That much is working
as my driver's AddDevice() routine is getting called 8 times and I'm creating
8 deviceNames that I can then open with CreateFile() to get 8 separate
HANDLES in an application.
But no matter which HANDLE I use in my application to write data out, the
data goes to LUN 0 within my device.
I had to change the routines in xferpkt.c of classpnp because my SCSI-2
device only supports 6-byte CDB (instead of the 10-byte ones created in
xferpkt). But nowhere did I find where either the 10-byte or 6-byte
CDB.LogicalUnitNumber is being setup.
Is this information perhaps in the FDO extension for SCSI devices from the
SCSI port driver or something?
Mike
"Don Burn" wrote:
> .
>
"Mike Fochtman" <MikeFo...@discussions.microsoft.com> wrote in message
news:C1D3EE3E-11DA-4F16...@microsoft.com...
Are you sure that nonzero LUNs on your device are known to PnP and the drivers are loaded to them?
> I had to change the routines in xferpkt.c of classpnp because my SCSI-2
> device only supports 6-byte CDB
classpnp is for disks (SBC) and CD/DVDs (MMC) only.
I think this field is obsolete and now the selection of LUN is done using some command which precedes the CDB flow.
Read the specs more. I think the current mechanism to distinguish across LUNs is another, not the CDB field.
"m" wrote:
> But they should all have separate device instances! You can get the LUN, or
> any other kind of device specific info from there - assuming that you _did_
> set it up properly on enum
>
I *do* have separate instances. My CreateDevice routine is being called 8
times, once for each LUN. The driver creates a unique DosDevice name for
each instance and the application can open each of the eight DosDevice names.
When using WriteFile() to any of the handles however, the packets going out
on the SCSI bus all have the same LUN in the Command Device Block, '0'.
The packet on the SCSI bus *does* have the correct TargetID loaded into it,
so that much is being maintained somewhere.
But nothing seems to be setting the LUN portion of the SCSI packet on the bus.
Mike
> .
>
"Maxim S. Shatskih" wrote:
> > xferpkt.c routines in classpnp. But the original version didn't seem to
> > setup the LogicalUnitNumber member of the CDB.
>
> I think this field is obsolete and now the selection of LUN is done using some command which precedes the CDB flow.
>
Even if the field is 'obsolete' in WIndows, the SCSI specification for SCSI
devices requires that the Command Device Block that is attached to all SCSI
transfers on the bus must have the TargetID and Logical Unit Number properly
embedded in them. I don't think it's a coincidence that the bit layout in
CDB6GENERIC and CDB10... and other CDB's in the WDK matches up with the
actual Command Device Block definitions in the SCSI-3 specification.
So somewhere between application and the SCSI HBA, *someone* has to make a
correlation between a particular device instance and the SCSI TargetID and
LUN of that device.
When the SCSI port first enumerates all the devices on the bus, it finds
eight instances of my device (because it responds to one TargetID with 8
different LUN's). My driver counts these and updates a 'nextAvailableNumber'
value in the registry under my key. So I know it's entered 8 times.
It also creates 8 unique DosDevice names that I can see from
QueryDosDevice() and use in CreateFile().
If it gets this far, and successfully opens, wouldn't that mean that each
instance is fully initialized and ready to go?
I can even do a WriteFile() to each, but the actual SCSI packet going across
the wires on the SCSI bus has LUN of 0.
Sorry if my tone is too strong here, I apologize for that. Just that the
SCSI bus has to have a LUN (SCSI, SCSI-2 and SCSI-3 standards have all
required this). So it seems like it has to be associated with the PDO
*somewhere*.
> Read the specs more. I think the current mechanism to distinguish across LUNs is another, not the CDB field.
>
Another? If you mean 'another device instance', I agree. But regardless of
what device instance, the packet being sent out the wire has to be populated
correctly by some driver in the stack. If not mine, then where?
Mike
"Maxim S. Shatskih" wrote:
> > But no matter which HANDLE I use in my application to write data out, the
> > data goes to LUN 0 within my device.
>
> Are you sure that nonzero LUNs on your device are known to PnP and the drivers are loaded to them?
>
Well before today, I would have said YES. I can use CreateFile() with
different device names, one for each LUN. But when I WriteFile() to any
HANDLE, it always comes out the LUN 0 of the device.
In HKEY_LOCAL_MACHINE/Hardware/Devicemap/SCSI.... I find the TargetID for
the device, but it only shows LUN 0 underneath that key. So now I'm not so
sure. Isn't Devicemap built from the enumeration of the bus, independent of
my driver?
If so, then I have to figure out why the LUN's aren't being enumerated by
the SCSI port driver / HBA. It's an Adaptec SCSI card and when I go into
their BIOS, it scans the bus and shows the device with 8 LUNs, so it seems
the HBA is there.
I know the hardware itself works with my previous generation driver (DDK
under NT 4.0). But that's a different generation SCSI card as well (PCI
instead of PCIe ).
Mike
"Mike Fochtman" <MikeFo...@discussions.microsoft.com> wrote in message
news:882086C5-1FB5-4BCE...@microsoft.com...
Look in Device Manager. Are the LUNs there?
I think that the LUN field in the CDB is obsoleted by the SCSI spec in 2000ies, am I wrong?
> transfers on the bus must have the TargetID and Logical Unit Number properly
> embedded in them.
TargetID was never embedded to the CDB.
> When the SCSI port first enumerates all the devices on the bus, it finds
> eight instances of my device (because it responds to one TargetID with 8
> different LUN's). My driver counts these and updates a 'nextAvailableNumber'
> value in the registry under my key. So I know it's entered 8 times.
So, you see the 8 instances in the Device Manager?
> I can even do a WriteFile() to each, but the actual SCSI packet going across
> the wires on the SCSI bus has LUN of 0.
How are you opening the file for WriteFile? how your driver creates the SRB?
Target - not, LUN - was a part of the CDB in obsolete specs.
For instance, the SBC-2 document I have at hand (2001) lists the following in READ(6):
0: opcode (==8)
1: 3 bits reserved (these were the LUN number in the obsolete spec of around 1993)
5 bits LBA
2: 8 bits LBA
3: 8 bits LBA
4: 8 bits length
5: control
So, no LUN number in the CDB modern days.
In modern SCSI, the CDBs are defined to be sent to I_T_L or I_T_L_Q nexus, with the nexus being established before sending a CDB. LUN number is used during establishment procedure of I_T_L nexus, not in a CDB.
The nexus establishment procedure depends on particular physical layer. Layers like USB Storage, SBP-2 or iSCSI can, for instance, add some additional headers to the SCSI request, while the usual wire-based parallel SCSI or SAS uses the message system for this.
In Windows at the miniport level, the SRB has Lun/QueueTag fields in it (they are not in CDB), and the miniport must use them for nexus establishment.
At the class driver level, just leave Bus/Target/Lun fields as zeroes in the SRB, the storage port will assign them itself.
"Maxim S. Shatskih" wrote:
> > Target and LUN are not part of CDB.
>
> Target - not, LUN - was a part of the CDB in obsolete specs.
Yes, you're both right about the TargetID, the Target is not in the CDB
itself, the adapter puts the TargetID on the SCSI address portion of the bus
while the LUN was part of the CDB transmitted on the data bus (in the older
SCSI specs).
>
> For instance, the SBC-2 document I have at hand (2001) lists the following in READ(6):
>
> 0: opcode (==8)
> 1: 3 bits reserved (these were the LUN number in the obsolete spec of around 1993)
> 5 bits LBA
> 2: 8 bits LBA
> 3: 8 bits LBA
> 4: 8 bits length
> 5: control
>
> So, no LUN number in the CDB modern days.
>
> In modern SCSI, the CDBs are defined to be sent to I_T_L or I_T_L_Q nexus, with the nexus being established before sending a CDB. LUN number is used during establishment procedure of I_T_L nexus, not in a CDB.
>
Ahhhh...
Now some light has been shed. This device I'm working with is an older
device built to the '93 spec. So it expects the LUN in the 6-byte CDB. It's
technically a 'SCSI Processor' device so it only responds to a few SCSI
commands, and I_T_L nexus is not one of them.
In answer to your other question, no I don't see all eight LUN's in the
Device Manager or in the HKEY_LOCAL_MACHINE registry. I suspect the 'modern'
SCSI adapter is not responding to the LUNs in this older device. When I put
this device on an older computer it *does* report 8 LUNs (running XP with an
older SCSI adapter (adaptec 2940UW)).
I find it hard to believe that the latest SCSI spec would *break* existing
equipment. Isn't a SCSI-2 compliant device (which this was in 1997 when it
was made), still supported?
> The nexus establishment procedure depends on particular physical layer. Layers like USB Storage, SBP-2 or iSCSI can, for instance, add some additional headers to the SCSI request, while the usual wire-based parallel SCSI or SAS uses the message system for this.
>
> In Windows at the miniport level, the SRB has Lun/QueueTag fields in it (they are not in CDB), and the miniport must use them for nexus establishment.
>
> At the class driver level, just leave Bus/Target/Lun fields as zeroes in the SRB, the storage port will assign them itself.
>
Well that's sort of what I was expecting at first (that the port driver
would add the appropriate Bus/Target/Lun to the Srb/Cdb, but it apparently is
doing it using ITL nexus instead of the older form within the CDB. (The
device probably ignores ITL nexus requests and since the LUN bits in the CDB
are zero, it just takes the data to LUN 0 of the device all the time)
My older legacy driver (for 32-bit and NT 4.0) didn't have to do anything
with LUN because it was automagically handled by the port driver. So I
expected the same with this. I expected since it doesn't support I_T_L the
port driver would revert to older SCSI-2 format and put LUN in the second
byte of CDB.
In order to get something working, I'm going to try
DeviceIoControl(IOCTL_SCSI_PASS_THROUGH) at the application level, directly
to the \\.\Scsi0 device. Then I'll see if I can talk to this older device by
hand building my own CDB with the LUN set.
Thanks for your help/explanation.
Mike
So, you can/cannot see the LUNs on the same OS depending on the adapter hardware?
This really looks like the device is no more SCSI-compliant.
Using an older SCSI Bus adapter, I *can* see all 8 LUNs being enumerated in
the registry on a Windows XP box. Using a newer SCSI bus adapter I *cannot*
see all 8 LUNs, only LUN0 in the registry on a WIndows 7 computer. The older
one is a PCI adapter and the newer is PCIe so I can't plug them into the same
computer / OS to try out. I'd have to install each OS on the opposite
machines to sort that out completely and I don't think the PCI machine will
support Windows 7 for the older PCI SCSI adapter.
I spoke with the hardware engineer for quite a while and came away with my
tail between my legs. He set me straight on this: The device responds to an
INQUIRY to any of the 8 LUNs. When a new command is started, once the target
is selected it first enters MESSAGE OUT phase where it gets an IDENTIFY
message from the initiator. That tells the Target what LUN this command is
for. *I* thought it looked at the bits in the CDB, but he told me that I was
wrong, that behavior is old SCSI-1 and his device uses the IDENTIFY message
to support to identify LUN as per SCSI-2. This is probably what you referred
to as negotiating the I-T-L nexus. Sorry for all *my* confusion on the
matter.
I looked on the T10 web site and apparently SCSI-2 (ANSI X3.131-1994) is
still an approved standard, next up for review in 2009 (ANSI typically
re-affirms the old standard every 5 years if there are no substantive
changes, last reviewed in 2004). The SCSI-3 standard seems to have been
broken down into a dozen or so separate documents, so I'm debating if I want
to buy all of them (at $30/each) just to find the one that covers this area.
Do you happen to know which SCSI-3 document this would be in?
The device hasn't changed so it couldn't very well suddenly not comply with
a standard written in 1994. I suspect the newer adapter cards are not
supporting this older standard any more and/or the port driver isn't
enumerating them. Problem is, the older adapter cards are hard to come by
any more.
I used DeviceIoControl(IOCTL_SCSI_PASS_THROUGH) to the Scsi0 port itself so
I could send my own command to the target. Works great for LUN0 but when I
just change the LUN to 1, the call to DeviceIoControl() fails with "The
system cannot find the file specified." So apparently somewhere in Windows
it won't let me arbitarily select what LUN to go to if it didn't detect it.
Seems a little counter to what DeviceIoCOntrol() is supposed to let me do.
Mike
Exactly so. On usual SCSI cable, I_T_L is established by IDENTIFY message.