I am trying to get Maximum LBA of the disk using SCSI Read Capacity Command.
I have created 10 byte CDB as follows
ccb->cam_flags = NO_DATA;
ccb->cdb[0] = READ_CAPACITY; /* 0x25 SCSI Opcode for Read Capacity Command */ ccb->cdb[1] = 0x01;
ccb->cdb[2] = 0;
ccb->cdb[3] = 0;
ccb->cdb[4] = 0;
ccb->cdb[5] = 0;
ccb->cdb[6] = 0;
ccb->cdb[7] = 0;
ccb->cdb[8] = 0x01;
ccb->cdb[9] = 0;
The SCSI command is successful. Unfortunately I am not getting the expected LBA and it is displaying it as zero.
My basic question is whether the SCSI CDB command created above is correct or not ?
Try to set ccb->cdb[1] to 0. Relative address bit should not be used in such case.
Related
I'm trying to use the DIO SPI mode on the ESP32 with the espidf (version 4.4).
But I encountered problems.
I have a ram device (ref 23LC1024) than can be accessed with several modes (single, dual, quad).
The single mode works perfectly (can write and read back)
The dual mode creates problems.
Here is how I configure the SPI bus (same setup for single or dual mode)
memset(&config, 0, sizeof(spi_bus_config_t));
config.mosi_io_num = MOSI_PIN;
config.miso_io_num = MISO_PIN;
config.sclk_io_num = SCLK_PIN;
config.quadwp_io_num = -1; // -1 not used
config.quadhd_io_num = -1; // -1 not used
config.flags = SPICOMMON_BUSFLAG_DUAL | SPICOMMON_BUSFLAG_MASTER;
spi_bus_initialize(VSPI_HOST, &config, SPI_DMA_DISABLED); // 0 DMA not used
Now the setup for the device (same setup for single mode or dual):
spi_device_interface_config_t devcfg = {
.clock_speed_hz = freq,
.command_bits = 8,
.address_bits = 24,
.dummy_bits = 8,
.mode = 0, // SPI MODE 0
.flags = 0,
.spics_io_num = _cs,
.queue_size = 1,
.pre_cb = NULL,
.post_cb = NULL};
ESP_ERROR_CHECK(spi_bus_add_device(VSPI_HOST, &devcfg, &data_Ram));
Now the setup for the transaction:
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.cmd = WRITE;
t.tx_buffer = data;
t.rx_buffer = NULL;
t.addr = address;
t.length = size * 8;
if (USE_DIO) // configure these flags in case of DIO
t.flags = SPI_TRANS_MODE_DIO | SPI_TRANS_MULTILINE_ADDR | SPI_TRANS_MULTILINE_CMD;
ESP_ERROR_CHECK(spi_device_transmit(data_Ram, &t)); // Transmit!
It works nicely in the single mode but with the dual mode I got the error:
E (1618) spi_master: check_trans_valid(699): Incompatible when setting to both multi-line mode and half duplex mode
Does it mean I cannot use DIO in half duplex mode with the SPI master library?
Is there something I should change in my setup ?
I tried to specify the SPI_DEVICE_HALFDUPLEX flag in the spi_device_interface_config_t. Does not help.
Unfortunately I did not find any example on internet.
Thanks for your heads up!
E (1618) spi_master: check_trans_valid(699): Incompatible when setting to both multi-line mode and half duplex mode means that you cannot use MISO and MOSI for transfering (multiline) AND use them at the same time (full duplex).
Set your device to half duplex to fix the problem:
spi_device_interface_config_t devcfg = {
.flags = SPI_DEVICE_HALFDUPLEX,
...
};
In my experience, SPI_TRANS_MULTILINE_ADDR doesn't work, at least with spi_device_transmit.
If your ram device allows it, try without the "multilined" address and command.
Background
I'm writing some dtrace program which tracks application socket file descriptors. Aim is to provide logs which help me spot leak of file descriptors in some very complex OS X application.
Here is my other question with very helpful answer.
Problem
I want that my program is logging address to which file descriptor has been connected to. In examples there is a code which partial do what I need: soconnect_mac.d, here is link to github.
soconnect_mac.d works great when applied on Firefox, but it completely fails in case of my application. Quick investigation shown that soconnect_mac.d is able to interpret only AF_INET (value 2) family address and som library used by my application is using AF_SYSTEM (value 32) family address.
I can't find anything which could help me convert received address to something what is human readable.
So far I've got this:
#!/usr/sbin/dtrace -s
inline int af_inet = 2 ; /* AF_INET defined in Kernel/sys/socket.h */
inline int af_inet6 = 30; /* AF_INET6 defined in Kernel/sys/socket.h */
inline int af_system = 32; /* AF_SYSTEM defined in Kernel/sys/socket.h */
… // some stuff
syscall::connect:entry
/pid == $target && isOpened[pid, arg0] == 1/
{
/* assume this is sockaddr_in until we can examine family */
this->s = (struct sockaddr_in *)copyin(arg1, arg2);
this->f = this->s->sin_family;
self->fileDescriptor = arg0;
}
/* this section is copied with pride from "soconnect_mac.d" */
syscall::connect:entry
/this->f == af_inet/
{
/* Convert port to host byte order without ntohs() being available. */
self->port = (this->s->sin_port & 0xFF00) >> 8;
self->port |= (this->s->sin_port & 0xFF) << 8;
/*
* Convert an IPv4 address into a dotted quad decimal string.
* Until the inet_ntoa() functions are available from DTrace, this is
* converted using the existing strjoin() and lltostr(). It's done in
* two parts to avoid exhausting DTrace registers in one line of code.
*/
this->a = (uint8_t *)&this->s->sin_addr;
this->addr1 = strjoin(lltostr(this->a[0] + 0ULL),
strjoin(".",
strjoin(lltostr(this->a[1] + 0ULL),
".")));
this->addr2 = strjoin(lltostr(this->a[2] + 0ULL),
strjoin(".",
lltostr(this->a[3] + 0ULL)));
self->address = strjoin(this->addr1, this->addr2);
}
/* this section is my */
syscall::connect:entry
/this->f == af_system/
{
/* TODO: Problem how to handle AF_SYSTEM address family */
/* Convert port to host byte order without ntohs() being available. */
self->port = (this->s->sin_port & 0xFF00) >> 8;
self->port |= (this->s->sin_port & 0xFF) << 8; // this also doen't work as it should
self->address = "system family address needed here";
}
// a fallback
syscall::connect:entry
/this->f && this->f != af_inet && this->f != af_system/
{
/* Convert port to host byte order without ntohs() being available. */
self->port = (this->s->sin_port & 0xFF00) >> 8;
self->port |= (this->s->sin_port & 0xFF) << 8;
self->address = strjoin("Can't handle family: ", lltostr(this->f));
}
syscall::connect:return
/self->fileDescriptor/
{
this->errstr = err[errno] != NULL ? err[errno] : lltostr(errno);
printf("%Y.%03d FD:%d Status:%s Address:%s Port:%d",
walltimestamp, walltimestamp % 1000000000 / 1000000,
self->fileDescriptor, this->errstr, self->address, self->port);
self->fileDescriptor = 0;
self->address = 0;
self->port = 0;
}
What is even more annoying my code has failed to read port number (I get 512 value instead one of this: 443, 8443, 5061).
IMO problem is first syscall::connect:entry where it is assumed that second argument can be treated as struct sockaddr_in. I'm guessing struct sockaddr_storage should be used in case of AF_SYSTEM address family, but I didn't found any documentation or source code which proves this in direct way.
My section with this->f == af_system condition properly catches events from application I'm investigating.
I have the issue with FMC controller when interfacing 64MB IS42S16400J-7BLI.
I'm using the CubeMX to set base configuration
static void MX_FMC_Init(void)
{
FMC_SDRAM_TimingTypeDef SdramTiming;
/** Perform the SDRAM1 memory initialization sequence
*/
hsdram1.Instance = FMC_SDRAM_DEVICE;
/* hsdram1.Init */
hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_11;
hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
/* SdramTiming */
SdramTiming.LoadToActiveDelay = 2;
SdramTiming.ExitSelfRefreshDelay = 7;
SdramTiming.SelfRefreshTime = 4;
SdramTiming.RowCycleDelay = 7;
SdramTiming.WriteRecoveryTime = 3;
SdramTiming.RPDelay = 2;
SdramTiming.RCDDelay = 2;
if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK)
{
Error_Handler();
}
}
and config the memory
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef* hsdram, FMC_SDRAM_CommandTypeDef* Command)
{
__IO uint32_t tmpmrd = 0;
/* Step 3: Configure a clock configuration enable command */
Command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 4: Insert 100 ms delay */
HAL_Delay(100);
/* Step 5: Configure a PALL (precharge all) command */
Command->CommandMode = FMC_SDRAM_CMD_PALL;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 6 : Configure a Auto-Refresh command */
Command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 4;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 7: Program the external memory mode register */
tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2 |
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
SDRAM_MODEREG_CAS_LATENCY_3 |
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = tmpmrd;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 8: Set the refresh rate counter */
/* (15.62 us x Freq) - 20 */
/* Set the device refresh counter */
HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT);
}
The memory and micro are connected according to the schematic
I can use only 8bit of addressing. In this configuration everything is perfect, i.e. I can read/write values and observe them in debug window. It limits me though to only 8MB of memory.
When I modify in settings 8bits up to 9/10/11bits to have more memory available it starts malfunctioning,i.e. garbage in some memory area.
I made customized board, but the same issue you going find on the STM32F429-disco board. So I reject rather the connections. I tried to play with the time delays like "Row to column delay" and increase all delays possible, but not luck. Any help would be appreciated.
From IS42S16400J-7BLI datasheet:
Internally configured as a quad-bank DRAM with a synchronous
interface. Each 16,777,216-bit bank is organized as 4,096 rows by 256
columns by 16 bits.
So, you should use 8 bit in ColumnBitsNumber. And you'll get 8 Mbytes (64 MBits/8) of memory.
I have a timer in XC8 MPlab with PIC16F690 that is running great.
I want to change its initial value. I could not find how to set a value into its register so it starts from that value.
I'm looking for the syntax for that register to fill it with data.
OPTION_REGbits.T0CS = 0; //setting timer
OPTION_REGbits.PSA = 0;
OPTION_REGbits.PS = 0b101; //setting the pre scale
INTCONbits.T0IE = 1;
ei(); //enable interrupts
Normally, for most registers, you can access by the name like in datasheet with XC8. So the register for Timer0 called TMR0 in datasheet is also TMR0 in XC8.
Your code can be rewritten like below:
T0CS = 0; // setting timer
PSA = 0;
PS = 0b101; // setting the pre scale
T0IE = 1;
TMR0 = 0x06;
ei(); // enable interrupts
Does windows have specific interface by which I can send a specific scsi command such Inquiry to scsi device ? I searched the net, found passing reference to SCSI Pass Through interface. But Its very Vague.
Is there any documentation for that API on how to use it??
#include <iostream>
#include <windows.h>
#include <winioctl.h>
#define ULONG_PTR ULONG
#include <ntddscsi.h> //from SDK
#include <spti.h> //from DDK
using namespace std;
int demo()
{
HANDLE hDisk;
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptdwb;
ULONG length = 0;
DWORD bytesReturn;
BYTE bufDataRead[64*1024+10];
int iRet;
hDisk = CreateFile(path,GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,OPEN_EXISTING,0,NULL
);
if (hDisk ==INVALID_HANDLE_VALUE) {
return 0;
}
ZeroMemory(&sptdwb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));
sptdwb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
sptdwb.sptd.PathId = 0;
sptdwb.sptd.TargetId = 1;
sptdwb.sptd.Lun = 0;
sptdwb.sptd.CdbLength = 6;
sptdwb.sptd.DataIn = SCSI_IOCTL_DATA_IN;
sptdwb.sptd.SenseInfoLength = 24;
sptdwb.sptd.DataTransferLength = 8;
sptdwb.sptd.TimeOutValue = 2;
sptdwb.sptd.DataBuffer = bufDataRead;
sptdwb.sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);
sptdwb.sptd.Cdb[0] = 0x12;
sptdwb.sptd.Cdb[1] = 0x00;
sptdwb.sptd.Cdb[2] = 0x00;
sptdwb.sptd.Cdb[3] = 0x00;
sptdwb.sptd.Cdb[4] = 0xFF;
sptdwb.sptd.Cdb[5] = 0x00;
length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
iRet = DeviceIoControl(hDisk,
IOCTL_SCSI_PASS_THROUGH_DIRECT,
&sptdwb,
length,
&sptdwb,
length,
&bytesReturn,
NULL);
if (0 == iRet) {
printf("inquiry fail");
return 0;
} else {
//Check returned data in sptdwb.sptd.DataBuffer.
}
return 0;
}
SCSI covers a vast amount of ground. Are you talking to a CD/DVD/Disk/Tape/Scanner or what.
For CD/DVD the best (and only) free reference for setup/read/write commands are to be found here: http://www.t10.org/drafts.htm
Re SPTI, there is some very basic documentation in the old 'Programmers guide to SCSI'. There is an article on an ASPI -> SPTI converter that can be found on the DDJ web site.
Bear in mind that SPTI is simply an API, it imposes nor knows anything about SCSI message content or format.
Brian Sawert, Addison Wesley 1998.
You can send SCSI commands to the SCSI Port driver by sending it an IRP_MJ_SCSI IRP, see http://msdn.microsoft.com/en-us/library/ff565387(VS.85).aspx. However, you will have to construct the SCSI CBD yourself, and I have yet to find a document which describes it.
Anymore, the SCSI commands are broken down into a number of specs. The INQUIRY command is in the SPC spec, while device type specific commands are broken down into several specs (i.e. block, ses, ...).