📄 tffsdrv26.c
字号:
{ /* enable interrupt generation in DiskOnChip */ TffsEnableIRQ (&tffsInfo.sockets[0]); } STEP++; /* 4 */ /* Register our major device # (or accept dynamically allocated * major #). */ if ((tmp = register_blkdev(tffs_major, tffs_str)) < 0) { PrintkError ("Can't get major %d", tffs_major); cleanup (STEP); return -EBUSY; } if (tffs_major == 0) /* we asked for dynamic major #, and we got it */ tffs_major = tmp; PrintkInfo ("use major device number %d", tffs_major); STEP++; /* 5 */#ifdef CONFIG_PROC_FS if ((tffsInfo.pProcDir = proc_mkdir(tffs_str, NULL)) == NULL) { PrintkWarning ("Can't create /proc/%s", tffs_str); }#endif STEP++; /* 6 */ /* initialize Open/Close mutex in "available" state */ sema_init (&open_close_mutex, 1); /* init sockets */ for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) init_socket (&tffsInfo.sockets[iSoc]); STEP++; /* 7 */#ifdef CONFIG_PM tffs_pm_init (); /* register with Power Manager */#endif STEP++; /* 8 */ return 0;}/******************************************************************************* * * * i n i t _ s o c k e t * * * * Initialize socket's I/O thread and all socket's disks. * * * * Parameters: * * psoc pointer to socket being initialized * * * *******************************************************************************/static void /* __init */ init_socket ( SocketInfo * psoc ){ int iDisk; if (psoc->fFound == 0) return; sema_init (&psoc->threadSemaphore, 0); /* initialized as "not available" */ /* Tell I/O thread to put up psoc->threadSemaphore when it's up and running */ psoc->io_thread_state = 2; /* start socket's I/O thread */ kernel_thread (socket_io_thread, (void *)psoc, 0); /* wait until socket's I/O thread is up and running */ down_interruptible (&psoc->threadSemaphore); /* socket's I/O thread has been started, and is currently waiting for * I/O requests to be posted to psoc->waitQueueHead. */ for (iDisk = 0; iDisk < psoc->wDevices; iDisk++) init_disk (&psoc->pDevices[iDisk]);}/******************************************************************************* * * * i n i t _ d i s k * * * * Initialize individual disk. s). * * * * Parameters: * * pdisk pointer to disk * * * *******************************************************************************/static void /* __init */ init_disk ( DeviceInfo * pdisk ){ struct gendisk * gd; int max_partitions; /* nobody has opened this disk yet */ pdisk->in_use = 0;#ifdef TFFS_STATISTIC memset (&pdisk->stat, 0, sizeof(pdisk->stat));#endif#ifdef CONFIG_PROC_FS procfs_register (pdisk);#endif /* allocate request queue for this disk */ spin_lock_init (&pdisk->rq_lock); pdisk->rq = blk_init_queue (disk_request_queue_handler, &pdisk->rq_lock); if (pdisk->rq == NULL) { PrintkError ("blk_init_queue() failed for disk 0x%x", pdisk->bHandle); return; } else pdisk->rq->queuedata = pdisk; /* Maximum number of file system partitions that we allow * on the disk (this doesn't include "raw" disk). */ max_partitions = ((1 << DEV2PART_SHIFT) - 1); /* allocate struct gendisk for this disk */ if ((gd = alloc_disk(max_partitions)) == NULL) { /* return previously allocated request queue to the system */ blk_cleanup_queue (pdisk->rq); pdisk->rq = NULL; PrintkError ("alloc_disk() failed for disk 0x%x", pdisk->bHandle); return; } else pdisk->gd = gd; gd->major = tffs_major; gd->first_minor = (pdisk->diskNo * (max_partitions + 1/*"raw" disk entry*/)); gd->fops = &tffs_bdev_ops; gd->queue = pdisk->rq; gd->private_data = pdisk; /* name this disk */ snprintf (gd->disk_name, sizeof(gd->disk_name), "%s%c", tffs_str, ('a' + (char)(pdisk->diskNo))); /* specify disk's capacity in 512-byte sectors */ set_capacity (gd, pdisk->dwSize); /* Tell kernel about this disk. Before add_disk() returns, * kernel will attempt to read Master Boot Record and parse * partition table(s) on this disk; it will post I/O requests * to pdisk->rq, and call disk_request_queue_handler() * to handle these request. */ add_disk (gd);}/******************************************************************************* * * * c l e a n u p * * * * Free all data structures alocated during driver's startup. * * * * Parameters: * * STEP specifies which resources to free * * * * Returns: void * * * *******************************************************************************/static void cleanup ( int STEP ){ int iSoc; if (STEP >= 8) { #ifdef CONFIG_PM tffs_pm_exit (); /* unregister from Power Manager */#endif } if (STEP >= 7) { /* For every socket, flush all socket's disks, and sleep until socket's * I/O thread handled all outstanding I/O requests and exited. */ for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) { if (tffsInfo.sockets[iSoc].fFound != 0) release_socket (&tffsInfo.sockets[iSoc]); } } if (STEP >= 6) {#ifdef CONFIG_PROC_FS remove_proc_entry (tffs_str, NULL); tffsInfo.pProcDir = NULL;#endif } if (STEP >= 5) { unregister_blkdev (tffs_major, tffs_str); } if (STEP >= 4) { /* disable_irq (tffs_irq); */ /* We should tell DiskOnChip to disable interrupt generation, but * unfortunately TrueFFS currently doesn't provide API for that. */ } if (STEP >= 3) { /* For all disks of all DiskOnChip sockets, write Quick Mount * records to them, abs.unmount them, and shut down TrueFFS. */ TffsCleanup (); } if (STEP >= 2) { /* if previously installed, remove DiskOnChip interrupt handler */ if (tffs_irq >= 0) free_irq (tffs_irq, &tffsInfo.sockets[0]); }}/******************************************************************************* * * * r e l e a s e _ s o c k e t * * * * Release DiskOnChip socket. * * * * Parameters: * * psoc pointer to socket being released * * * * Returns: void * * * *******************************************************************************/static void /* __exit */ release_socket ( SocketInfo * psoc ){ int iDisk; if (psoc->fFound == 0) return; /* Release all socket's disks; this involves flushing all partitions * on all these disks. */ for (iDisk = 0; iDisk < psoc->wDevices; iDisk++) release_disk (&psoc->pDevices[iDisk]); if (psoc->io_thread_state == 1) /* I/O thread is running */ { /* Tell I/O thread to complete handling of all outstanding I/O requests, * put up psoc->threadSemaphore, and exit. */ psoc->io_thread_state = 2; /* in case socket's I/O thread is currently sleeping, wake it up */ wake_up (&psoc->waitQueueHead); /* now wait for I/O thread to exit */ down_interruptible (&psoc->threadSemaphore); }}/******************************************************************************* * * * r e l e a s e _ d i s k * * * * Release disk. * * * * Parameters: * * pdisk pointer to disk being released * * * * Returns: void * * * *******************************************************************************/staticvoid /* __exit */ release_disk (DeviceInfo * pdisk){ if (pdisk->gd != NULL) { del_gendisk (pdisk->gd); pdisk->gd = NULL; } if (pdisk->rq != NULL) { blk_cleanup_queue (pdisk->rq); pdisk->rq = NULL; }#ifdef CONFIG_PROC_FS procfs_unregister (pdisk);#endif}/******************************************************************************* * * * d i s k _ o p e n * * * * Open disk (i.e. block_device_operations.open()). * * * * Parameters: * * * * inode inode pointer * * filp file pointer * * * * Returns: zero if success, otherwise negative error code * * * *******************************************************************************/staticint disk_open ( struct inode * inode,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -