📄 myudisk.c
字号:
/* unlock the device */ up (&dev->sem); /* return that we did not understand this ioctl call */ return -ENOTTY; }/** * myudisk_write_bulk_callback */static void myudisk_write_bulk_callback (struct urb *urb){ struct my_udisk *dev = (struct my_udisk *)urb->context; dbg(" - minor %d", dev->minor); if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)) { dbg(" - nonzero write bulk status received: %d", urb->status); return; } return;}static int myudisk_request(request_queue_t *request_queue, int rw, struct buffer_head *sbh){ unsigned long total; //int *make_oops = NULL; // CR: access to this pointer will cause Oops, for debug only. //INIT_REQUEST; //devno = DEVICE_NR(CURRENT->rq_dev); /*if(devno>MAX_DEVICES); { printk("The device number is too larage!!!\n"); return 0; }*/ //struct my_udisk *dev = CURRENT->rq_dev; struct my_udisk *dev = minor_table[0]; int retval; if(dev == NULL) { printk("Point to a unknown device !!! the dev is NULL\n"); return 0; } if (dev->udev == NULL) { printk("the dev->udev is NULL!!!\n"); return -ENODEV; } dbg("%s sector rsector = %lu, blocknr = %lu\n", rw == READ ? "read" : "write", sbh->b_rsector, sbh->b_blocknr); //offset = sbh->b_rsector * myudisk_sectorsize; total = (unsigned long)sbh->b_size;//计算需要访问的地址和大小 __u32 nLUN = (__u32)(PARTION_offset + sbh->b_rsector); /* access beyond end of the device */ if (total+nLUN> myudisk_size) { dbg("Error: access beyond end of the device"); /* error in request */ buffer_IO_error(sbh); return 0; } //判断访问地址是否越界 dbg("offset = %lu, total = %lu\n", nLUN, total); //printk("The request has to the read write function!!!\n");//singal of using for the debug! struct cmnd_struct *com; com = kmalloc (sizeof(struct cmnd_struct),GFP_KERNEL); //////////////////////////////////////////////////////////////**********************///////////////// if (rw == READ) { //如果是读操作,从虚拟盘的内存中复制数据到缓冲区中 //memcpy(bh_kmap(sbh), myudisk_storage+offset, total); dbg("To the Read request!!!\n"); memset(dev->bulk_in_buffer,0,dev->bulk_in_size); com->cmnd[0] = 0x28; com->cmnd[1] = 0; com->cmnd[2] = ((unsigned char)nLUN>>24) & 0xff; com->cmnd[3] = ((unsigned char)nLUN>>16) & 0xff; com->cmnd[4] = ((unsigned char)nLUN>>8) & 0xff; com->cmnd[5] = ((unsigned char)nLUN) & 0xff; com->cmnd[7] = (unsigned char)((total/myudisk_soft)>>8) & 0xff; com->cmnd[8] = (unsigned char)(total/myudisk_soft) & 0xff; com->cmd_len = 12; com->data_payload_size = (unsigned long)sbh->b_size; com->sc_data_direction = SCSI_DATA_READ; com->tag = 0x12345678;; myudisk_Bulk_transport(dev->udev,dev->interface, com, dev->bulk_in_buffer, dev->bulk_in_size, dev->bulk_in_endpointAddr, dev->bulk_out_endpointAddr); memcpy(bh_kmap(sbh), dev->bulk_in_buffer,sbh->b_size); memset(dev->bulk_in_buffer,0,dev->bulk_in_size); dbg("usb_bulk_msg has successfully!!\n"); retval = (unsigned long)sbh->b_size; } else if (rw == WRITE) //如果是写操作,从缓冲区中复制数据到虚拟盘的内存中 { memset(dev->bulk_out_buffer,0,dev->bulk_out_size); memcpy(dev->bulk_out_buffer, bh_kmap(sbh), total); com->cmnd[0] = 0x2A; com->cmnd[1] = 0; com->data_payload_size = total; com->cmnd[2] = ((unsigned char)nLUN>>24) & 0xff; com->cmnd[3] = ((unsigned char)nLUN>>16) & 0xff; com->cmnd[4] = ((unsigned char)nLUN>>8) & 0xff; com->cmnd[5] = ((unsigned char)nLUN) & 0xff; com->cmnd[7] = (unsigned char)((total/myudisk_soft)>>8) & 0xff; com->cmnd[8] = (unsigned char)(total/myudisk_soft) & 0xff; com->tag = 0x12345678; com->cmd_len = 12; com->sc_data_direction = SCSI_DATA_WRITE; myudisk_Bulk_transport(dev->udev,dev->interface, com, dev->bulk_out_buffer, dev->bulk_out_size, dev->bulk_in_endpointAddr, dev->bulk_out_endpointAddr); memset(dev->bulk_out_buffer,0,dev->bulk_out_size); } else { /* can't happen */ dbg("cmd == %d is invalid\n", rw); } /* successful */ sbh->b_end_io(sbh,1); //结束读写操作 kfree(com); return 0;}/** * myudisk_probe * * Called by the usb core when a new device is connected that it thinks * this driver might be interested in. */static void * myudisk_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id){ struct my_udisk *dev = NULL; struct usb_interface *interface; struct usb_interface_descriptor *iface_desc; struct usb_endpoint_descriptor *endpoint; int minor; int buffer_size; int i; char name[10]; dbg("myudisk_probe()"); printk("The core has to here !!!!\n"); /* See if the device offered us matches what we can accept */ if ((udev->descriptor.idVendor != MY_UDISK_VENDOR_ID) || (udev->descriptor.idProduct != MY_UDISK_PRODUCT_ID)) { return NULL; } printk("drivers has successfully detected the device !!\n"); /* select a "subminor" number (part of a minor number) */ down (&minor_table_mutex); for (minor = 0; minor < MAX_DEVICES; ++minor) { if (minor_table[minor] == NULL) break; } if (minor >= MAX_DEVICES) { info ("Too many devices plugged in, can not handle this device.\n"); goto exit; } /* allocate memory for our device state and intialize it */ dev = kmalloc (sizeof(struct my_udisk), GFP_KERNEL); if (dev == NULL) { err ("Out of memory"); goto exit; } memset (dev, 0x00, sizeof (*dev)); minor_table[minor] = dev; printk("The subminor is %d The device is %p\n",minor,minor_table[minor]); interface = &udev->actconfig->interface[ifnum]; init_MUTEX (&dev->sem); dev->udev = udev; dev->interface = interface; dev->minor = minor; /* set up the endpoint information */ /* check out the endpoints */ iface_desc = &interface->altsetting[0]; for (i = 0; i < iface_desc->bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i]; if ((endpoint->bEndpointAddress & 0x80) && ((endpoint->bmAttributes & 3) == 0x02)) { /* we found a bulk in endpoint */ buffer_size = 4096; dev->bulk_in_size = buffer_size; dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; dev->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL); if (!dev->bulk_in_buffer) { err("Couldn't allocate bulk_in_buffer"); goto error; } } if (((endpoint->bEndpointAddress & 0x80) == 0x00) && ((endpoint->bmAttributes & 3) == 0x02)) { /* we found a bulk out endpoint */ dev->write_urb = usb_alloc_urb(0); if (!dev->write_urb) { err("No free urbs available"); goto error; } buffer_size = 4096; dev->bulk_out_size = buffer_size; dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; dev->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL); if (!dev->bulk_out_buffer) { err("Couldn't allocate bulk_out_buffer"); goto error; } FILL_BULK_URB(dev->write_urb, udev, usb_sndbulkpipe(udev, endpoint->bEndpointAddress), dev->bulk_out_buffer, buffer_size, myudisk_write_bulk_callback, dev); } } /* initialize the devfs node for this device and register it */ sprintf(name, "myudisk%d", dev->minor); dev->devfs = devfs_register (usb_devfs_handle, name, DEVFS_FL_DEFAULT, USB_MAJOR, MY_UDISK_MINOR_BASE + dev->minor, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, &myudisk_fops, NULL);///////////////////////////////////////////////////////////////////////////////This part is to read the flush's capicity and MBR information struct cmnd_struct *com;com = kmalloc (sizeof(struct cmnd_struct),GFP_KERNEL);if(com == NULL){ dbg("The memory on the com is unavailable !"); goto error;}memset(dev->bulk_in_buffer,0,dev->bulk_in_size);com->cmnd[0] = 0x25;com->tag = 0;com ->sc_data_direction = SCSI_DATA_READ ;com->cmnd[1] = 0;com->cmd_len = 12; myudisk_Bulk_transport(dev->udev, dev->interface, com, dev->bulk_in_buffer, dev->bulk_in_size, dev->bulk_in_endpointAddr, dev->bulk_out_endpointAddr);//This is to send the command and receive data from deviceprintk("To the after the read capity!");if(dev == NULL){ printk("The dev is NULL!\n"); goto error;}BLOCK_num = ( ((dev->bulk_in_buffer[0] )<< 24) | ((dev->bulk_in_buffer[1])<< 16) | ((dev->bulk_in_buffer[2]) << 8) | (dev->bulk_in_buffer[3]) ) + 1;//(__u32*)buffer; block number LBN(n-1)myudisk_soft = ( ((dev->bulk_in_buffer[4]) << 24) | ((dev->bulk_in_buffer[5]) << 16) | ((dev->bulk_in_buffer[6]) << 8) | (dev->bulk_in_buffer[7]) );//(__u32*)buffer+4;block size.myudisk_size = BLOCK_num * myudisk_soft;//device's capicity by bitesSECTOR_num = (myudisk_size/myudisk_hard);//device's sector numberprintk("The size is %u,The block size is %u,the num is %u",myudisk_size,myudisk_soft,BLOCK_num);memset(dev->bulk_in_buffer,0,dev->bulk_in_size);kfree(com); //////////////////***************************************************///////////////////////////this is to read MBR information but still have some problem __u32 nrBlock = 0;//read from the zero sector unsigned long size = 512;//the read block size the first 512 bites is the MBR information struct cmnd_struct *cs; cs = kmalloc (sizeof(struct cmnd_struct),GFP_KERNEL); if(cs == NULL) { dbg("The memory on the cs is unavailable !"); goto error; } cs->cmnd[0] = 0x28; cs->cmnd[1] =0; cs->cmnd[2] = ((unsigned char)nrBlock>>24) & 0xff; cs->cmnd[3] = ((unsigned char)nrBlock>>16) & 0xff; cs->cmnd[4] = ((unsigned char)nrBlock>>8) & 0xff; cs->cmnd[5] = ((unsigned char)nrBlock) & 0xff; cs->cmnd[7] = (unsigned char)((size/myudisk_soft)>>8) & 0xff; cs->cmnd[8] = (unsigned char)(size/myudisk_soft) & 0xff; cs ->tag = 0x12345678; cs->cmd_len = 12; cs->sc_data_direction = SCSI_DATA_READ; cs->data_payload_size = 512; myudisk_Bulk_transport(dev->udev, dev->interface, cs, dev->bulk_in_buffer, dev->bulk_in_size, dev->bulk_in_endpointAddr, dev->bulk_out_endpointAddr); __u32 startSector,sectorsNum; startSector = 0; sectorsNum = 0; for(i = 3; i>=1; i--)//computer the starter sector and the offset of the device { startSector += dev->bulk_in_buffer[0x01c6 + i]; sectorsNum += dev->bulk_in_buffer[0x01ca + i]; startSector <<= 8; sectorsNum <<= 8; } startSector += dev->bulk_in_buffer[0x01c6]; sectorsNum += dev->bulk_in_buffer[0x01ca]; dbg("The disk started at sector %X.\n",startSector); dbg("The disk has %X sectors.\n",sectorsNum); PARTION_offset = startSector; dbg("The disk offset with %X sectors.",PARTION_offset); printk("Next is the disk MBR and DPT information.\n"); for(i = 0; i < 512; i++){ printk("%X ",dev->bulk_in_buffer[i]); if(i == 445)////////////////////////////////the first 445 bites is the preboot information the last is the partation information printk("\nNow is the partition table.\n"); if(i%8 == 0) printk("\n"); } kfree(cs);////////////////////////////////////////////////////////////////////////////////// /* let the user know what node this device is now attached to */ info ("My UDisk device now attached to myudisk%d", dev->minor); goto exit; error: myudisk_delete (dev); dev = NULL;exit: up (&minor_table_mutex); return dev;}/** * myudisk_disconnect * * Called by the usb core when the device is removed from the system. *//*********************************************************************** * Helper routines ***********************************************************************//* Calculate the length of the data transfer (not the command) for any * given SCSI command (adapted from usb__stor_transfer_length()) */unsigned int myudisk_transfer_length(struct cmnd_struct *cs){ int doDefault = 0; unsigned int len = 0; /* This table tells us: X = command not supported L = return length in cmnd[4] (8 bits). M = return length in cmnd[8] (8 bits). G = return length in cmnd[3] and cmnd[4] (16 bits) H = return length in cmnd[7] and cmnd[8] (16 bits) I = return length in cmnd[8] and cmnd[9] (16 bits) C = return length in cmnd[2] to cmnd[5] (32 bits) D = return length in cmnd[6] to cmnd[9] (32 bits) B = return length in blocksize so we use buff_len R = return length in cmnd[2] to cmnd[4] (24 bits) S = return length in cmnd[3] to cmnd[5] (24 bits) T = return length in cmnd[6] to cmnd[8] (24 bits) U = return length in cmnd[7] to cmnd[9] (24 bits) 0-9 = fixed return length V = 20 bytes W = 24 bytes Z = return length is mode dependant or not in command, use buff_len */ static char *lengths = /* 0123456789ABCDEF 0123456789ABCDEF */ "00XLZ6XZBXBBXXXB" "00LBBLG0R0L0GG0X" /* 00-1F */ "XXXXT8XXB4B0BBBB" "ZZZ0B00HCSSZTBHH" /* 20-3F */ "M0HHB0X000H0HH0X" "XHH0HHXX0TH0H0XX" /* 40-5F */ "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 60-7F */ "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 80-9F */ "X0XXX00XB0BXBXBB" "ZZZ0XUIDU000XHBX" /* A0-BF */ "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */ "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */ /* Commands checked in table: CHANGE_DEFINITION 40 COMPARE 39 COPY 18 COPY_AND_VERIFY 3a ERASE 19 ERASE_10 2c ERASE_12 ac EXCHANGE_MEDIUM a6 FORMAT_UNIT 04 GET_DATA_BUFFER_STATUS 34 GET_MESSAGE_10 28 GET_MESSAGE_12 a8 GET_WINDOW 25 !!! Has more data than READ_CAPACITY, need to fix table INITIALIZE_ELEMENT_STATUS 07 !!! REASSIGN_BLOCKS luckily uses buff_len INQUIRY 12 LOAD_UNLOAD 1b LOCATE 2b LOCK_UNLOCK_CACHE 36 LOG_SELECT 4c LOG_SENSE 4d MEDIUM_SCAN 38 !!! This was M MODE_SELECT6 15 MODE_SELECT_10 55 MODE_SENSE_6 1a MODE_SENSE_10 5a MOVE_MEDIUM a5 OBJECT_POSITION 31 !!! Same as SEARCH_DATA_EQUAL PAUSE_RESUME 4b PLAY_AUDIO_10 45 PLAY_AUDIO_12 a5 PLAY_AUDIO_MSF 47 PLAY_AUDIO_TRACK_INDEX 48 PLAY_AUDIO_TRACK_RELATIVE_10 49 PLAY_AUDIO_TRACK_RELATIVE_12 a9 POSITION_TO_ELEMENT 2b PRE-FETCH 34 PREVENT_ALLOW_MEDIUM_REMOVAL 1e PRINT 0a !!! Same as WRITE_6 but is always in bytes READ_6 08 READ_10 28 READ_12 a8 READ_BLOCK_LIMITS 05 READ_BUFFER 3c READ_CAPACITY 25 READ_CDROM_CAPACITY 25 READ_DEFECT_DATA 37 READ_DEFECT_DATA_12 b7 READ_ELEMENT_STATUS b8 !!! Think this is in bytes READ_GENERATION 29 !!! Could also be M? READ_HEADER 44 !!! This was L READ_LONG 3e READ_POSITION 34 !!! This should be V but conflicts with PRE-FETCH READ_REVERSE 0f READ_SUB-CHANNEL 42 !!! Is this in bytes? READ_TOC 43 !!! Is this in bytes? READ_UPDATED_BLOCK 2d REASSIGN_BLOCKS 07 RECEIVE 08 !!! Same as READ_6 probably in bytes though RECEIVE_DIAGNOSTIC_RESULTS 1c RECOVER_BUFFERED_DATA 14 !!! For PRINTERs this is bytes RELEASE_UNIT 17 REQUEST_SENSE 03 REQUEST_VOLUME_ELEMENT_ADDRESS b5 !!! Think this is in bytes RESERVE_UNIT 16 REWIND 01 REZERO_UNIT 01 SCAN 1b !!! Conflicts with various commands, should be L SEARCH_DATA_EQUAL 31 SEARCH_DATA_EQUAL_12 b1 SEARCH_DATA_LOW 30 SEARCH_DATA_LOW_12 b0 SEARCH_DATA_HIGH 32 SEARCH_DATA_HIGH_12 b2 SEEK_6 0b !!! Conflicts with SLEW_AND_PRINT SEEK_10 2b SEND 0a !!! Same as WRITE_6, probably in bytes though SEND 2a !!! Similar to WRITE_10 but for scanners SEND_DIAGNOSTIC 1d SEND_MESSAGE_6 0a !!! Same as WRITE_6 - is in bytes SEND_MESSAGE_10 2a !!! Same as WRITE_10 - is in bytes SEND_MESSAGE_12 aa !!! Same as WRITE_12 - is in bytes SEND_OPC 54 SEND_VOLUME_TAG b6 !!! Think this is in bytes SET_LIMITS 33 SET_LIMITS_12 b3 SET_WINDOW 24 SLEW_AND_PRINT 0b !!! Conflicts with SEEK_6 SPACE 11 START_STOP_UNIT 1b STOP_PRINT 1b SYNCHRONIZE_BUFFER 10 SYNCHRONIZE_CACHE 35 TEST_UNIT_READY 00 UPDATE_BLOCK 3d VERIFY 13 VERIFY 2f VERIFY_12 af WRITE_6 0a WRITE_10 2a WRITE_12 aa WRITE_AND_VERIFY 2e WRITE_AND_VERIFY_12 ae WRITE_BUFFER 3b WRITE_FILEMARKS 10 WRITE_LONG 3f WRITE_SAME 41 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -