Hi, I have got a cypress usb-ide bridge and I would like to tune or monitor my disk with tools like hdparm, hddtemp or smartctl.
My controller support a way to send raw ATA command to the disk with something call atacb (see http://download.cypress.com.edgesuite.net/design_resources/datasheets/contents/cy7c68300c_8.pdf). First I start to add support for atacb in applications like smartctl. But there is some disadvantages : - I need to patch all application - A race is possible if there other accesses, because the emulation can be split in 2 atacb scsi transactions. One for sending the command, one for reading the register (if ck_cond is set). So the idea to implement a SAT emulation for such device came to my mind. First I want to ask, are there usb mass storage device that support SAT ? After some reading it seems impossible. Mass storage transparent scsi requires spc2 that only support fixed sense (starting with 0x70 or 0x71). But SAT need a sense with descriptor defined in spc3 (starting with 0x72 or 0x73). So SAT is not compatible with the sense format of mass storage ? For doing the emulation, I want to provide a special proto_handler. But I don't know what the best way to send command in my emulation layer : should I use usb_stor_invoke_transport or directly use us->transport. using usb_stor_invoke_transport save me lot's trouble of implementing error handling, but I can't control what I do. What should I do if I got an error after sending the first command and ck_cond is set ? Should I still try to read the register ? Is it safe to try to read the register if the first command did autosense ? Or should I only send the command, and read the register and compute the sense key, asc and ascq from registers ? For the moment, my "draft" code look something like [1]. Any comments ? Matthieu [1] void usb_stor_transparent_scsi_command_atacb(struct scsi_cmnd *srb, struct us_data *us) { if (srb->cmnd[0] != ATA_16) { usb_stor_invoke_transport(srb, us); return; } if (srb->cmnd[0] == ATA_16) { unsigned char save_cmnd[MAX_COMMAND_SIZE]; memcpy(save_cmnd, srb->cmnd, sizeof(save_cmnd)); memset(srb->cmnd, 0, sizeof(srb->cmnd)); /* first rebuild the command */ srb->cmnd[0] = 0x24; srb->cmnd[1] = 0x24; srb->cmnd[2] = 0; /* realy needed ? isd200 don't do that */ if (save_cmnd[14] == WIN_PIDENTIFY || save_cmnd[14] == WIN_IDENTIFY) srb->cmnd[2] |= (1<<7); srb->cmnd[3] = 0xff - 1; srb->cmnd[4] = 1; srb->cmnd[6] = save_cmnd[4]; srb->cmnd[7] = save_cmnd[6]; srb->cmnd[8] = save_cmnd[8]; srb->cmnd[9] = save_cmnd[10]; srb->cmnd[10] = save_cmnd[12]; srb->cmnd[11] = save_cmnd[13]; srb->cmnd[12] = save_cmnd[14]; /* XXX check of lba48 flied are set */ if (save_cmnd[1] & 0x01) {/* extended bit set */ if (save_cmnd[3] || save_cmnd[5] || save_cmnd[7] || save_cmnd[9] || save_cmnd[11]) printk("unsupported LBA48\n"); } usb_stor_invoke_transport(srb, us); if ((srb->result != (DID_ERROR << 16) && srb->result != (DID_ABORT << 16)) && save_cmnd[2] & 0x20) { /* ck_cond */ /* read regs and put them in sense */ int temp_result; struct scsi_eh_save ses; unsigned char sk, asc, ascq; unsigned char regs[8]; unsigned char *sb = srb->sense_buffer; unsigned char *desc = sb + 8; /* usb_stor_invoke_transport should do that when clearing sense */ if (sb[0] == 0) memset(sb, 0, sizeof(srb->sense_buffer)); /* save sense info */ sk = sb[2]; asc = sb[12]; ascq = sb[13]; /* read registers */ srb->cmnd[2] = 1; scsi_eh_prep_cmnd(srb, &ses, NULL, 0, 0); srb->request_buffer = regs; srb->request_bufflen = sizeof(regs); srb->sc_data_direction = DMA_FROM_DEVICE; usb_stor_invoke_transport(srb, us); /* XXX check error here */ scsi_eh_restore_cmnd(srb, &ses); /* build the sense */ sb[1] = sk; sb[2] = asc; sb[3] = ascq; sb[0] = 0x72; desc[0] = 0x09; /* ATA_RETURN_DESCRIPTOR */ sb[7] = 14; desc[1] = 12; desc[2] = 0x00; desc[3] = regs[1]; desc[5] = regs[2]; desc[7] = regs[3]; desc[9] = regs[4]; desc[11] = regs[5]; desc[12] = regs[6]; desc[13] = regs[7]; srb->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; } memcpy(srb->cmnd, save_cmnd, sizeof(save_cmnd)); } } - To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html