⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xd.c.txt

📁 Linux块设备驱动分析与模拟实现
💻 TXT
📖 第 1 页 / 共 3 页
字号:
  1 /*
  2  * This file contains the driver for an XT hard disk controller (at least the DTC 5150X) for Linux.
  3  *
  4  * Author: Pat Mackinlay, smackinla@cc.curtin.edu.au
  5  * Date: 29/09/92
  6  * 
  7  * Revised: 01/01/93, ...
  8  *
  9  * Ref: DTC 5150X Controller Specification (thanks to Kevin Fowler, kevinf@agora.rain.com)
 10  * Also thanks to: Salvador Abreu, Dave Thaler, Risto Kankkunen and Wim Van Dorst.
 11  */
 12 
 13 
 14 #include <linux/errno.h>
 15 #include <linux/sched.h>
 16 #include <linux/fs.h>
 17 #include <linux/kernel.h>
 18 #include <linux/genhd.h>
 19 #include <linux/xd.h>
 20 
 21 #include <asm/system.h>
 22 #include <asm/io.h>
 23 #include <asm/segment.h>
 24 #include <asm/dma.h>
 25 
 26 #define MAJOR_NR XT_DISK_MAJOR
 27 #include "blk.h"
 28 
 29 XD_INFO xd_info[XD_MAXDRIVES];
 30 
 31 /* If you try this driver and find that your card is not detected by the driver at bootup, you need to add your BIOS
 32    signature and details to the following list of signatures. A BIOS signature is a string embedded into the first
 33    few bytes of your controller's on-board ROM BIOS. To find out what yours is, use something like MS-DOS's DEBUG
 34    command. Run DEBUG, and then you can examine your BIOS signature with:
 35 
 36         d xxxx:0000
 37 
 38    where xxxx is the segment of your controller (like C800 or D000 or something). On the ASCII dump at the right, you should
 39    be able to see a string mentioning the manufacturer's copyright etc. Add this string into the table below. The parameters
 40    in the table are, in order:
 41 
 42         offset                  ; this is the offset (in bytes) from the start of your ROM where the signature starts
 43         signature               ; this is the actual text of the signature
 44         xd_?_init_controller    ; this is the controller init routine used by your controller
 45         xd_?_init_drive         ; this is the drive init routine used by your controller
 46 
 47    The controllers directly supported at the moment are: DTC 5150x, WD 1004A27X, ST11M/R and override. If your controller is
 48    made by the same manufacturer as one of these, try using the same init routines as they do. If that doesn't work, your
 49    best bet is to use the "override" routines. These routines use a "portable" method of getting the disk's geometry, and
 50    may work with your card. If none of these seem to work, try sending me some email and I'll see what I can do <grin>.
 51 
 52    NOTE: You can now specify your XT controller's parameters from the command line in the form xd=TYPE,IRQ,IO,DMA. The driver
 53    should be able to detect your drive's geometry from this info. (eg: xd=0,5,0x320,3 is the "standard"). */
 54 
 55 static XD_SIGNATURE xd_sigs[] = {
 56         { 0x0000,"Override geometry handler",NULL,xd_override_init_drive,"n unknown" }, /* Pat Mackinlay, smackinla@cc.curtin.edu.au (pat@gu.uwa.edu.au) */
 57         { 0x000B,"CXD23A Not an IBM ROM (C)Copyright Data Technology Corp 12/03/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Pat Mackinlay, smackinla@cc.curtin.edu.au (pat@gu.uwa.edu.au) */
 58         { 0x0008,"07/15/86 (C) Copyright 1986 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Digital 1002AWX1" }, /* Ian Justman, citrus!ianj@csusac.ecs.csus.edu */
 59         { 0x0008,"06/24/88 (C) Copyright 1988 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Digital 1004A27X" }, /* Dave Thaler, thalerd@engin.umich.edu */
 60         { 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Digital WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */
 61         { 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */
 62         { 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */
 63         { 0x1000,"(c)Copyright 1987 SMS",xd_omti_init_controller,xd_omti_init_drive,"n OMTI 5520" }, /* Dirk Melchers, dirk@merlin.nbg.sub.org */
 64 };
 65 static u_char *xd_bases[] =
 66 {
 67         (u_char *) 0xC8000,(u_char *) 0xCA000,(u_char *) 0xCC000,
 68         (u_char *) 0xCE000,(u_char *) 0xD0000,(u_char *) 0xD8000,
 69         (u_char *) 0xE0000
 70 };
 71 
 72 static struct hd_struct xd[XD_MAXDRIVES << 6];
 73 static int xd_sizes[XD_MAXDRIVES << 6],xd_access[XD_MAXDRIVES] = { 0,0 };
 74 static int xd_blocksizes[XD_MAXDRIVES << 6];
 75 static struct gendisk xd_gendisk = { MAJOR_NR,"xd",6,1 << 6,XD_MAXDRIVES,xd_geninit,xd,xd_sizes,0,(void *) xd_info,NULL };
 76 static struct file_operations xd_fops = { NULL,block_read,block_write,NULL,NULL,xd_ioctl,NULL,xd_open,xd_release,block_fsync };
 77 
 78 static struct wait_queue *xd_wait_int = NULL,*xd_wait_open = NULL;
 79 static u_char xd_valid[XD_MAXDRIVES] = { 0,0 };
 80 static u_char xd_drives = 0,xd_irq = 0,xd_dma = 0,xd_maxsectors,xd_override = 0,xd_type = 0;
 81 static u_short xd_iobase = 0;
 82 
 83 /* xd_init: grab the IRQ and DMA channel and initialise the drives */
 84 u_long xd_init (u_long mem_start,u_long mem_end)
 85 {
 86         u_char i,controller,*address;
 87         
 88         if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) {
 89                 printk("xd_init: unable to get major number %d\n",MAJOR_NR);
 90                 return (mem_start);
 91         }
 92         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
 93         read_ahead[MAJOR_NR] = 8;       /* 8 sector (4kB) read ahead */
 94         xd_gendisk.next = gendisk_head;
 95         gendisk_head = &xd_gendisk;
 96 
 97         if (xd_detect(&controller,&address)) {
 98 
 99                 printk("xd_init: detected a%s controller (type %d) at address %p\n",xd_sigs[controller].name,controller,address);
100                 if (controller)
101                         xd_sigs[controller].init_controller(address);
102                 xd_drives = xd_initdrives(xd_sigs[controller].init_drive);
103                 
104                 printk("xd_init: detected %d hard drive%s (using IRQ%d & DMA%d)\n",xd_drives,xd_drives == 1 ? "" : "s",xd_irq,xd_dma);
105                 for (i = 0; i < xd_drives; i++)
106                         printk("xd_init: drive %d geometry - heads = %d, cylinders = %d, sectors = %d\n",i,xd_info[i].heads,xd_info[i].cylinders,xd_info[i].sectors);
107 
108                 if (!request_irq(xd_irq,xd_interrupt_handler)) {
109                         if (request_dma(xd_dma)) {
110                                 printk("xd_init: unable to get DMA%d\n",xd_dma);
111                                 free_irq(xd_irq);
112                         }
113                 }
114                 else
115                         printk("xd_init: unable to get IRQ%d\n",xd_irq);
116         }
117         return mem_start;
118 }
119 
120 /* xd_detect: scan the possible BIOS ROM locations for the signature strings */
121 static u_char xd_detect (u_char *controller,u_char **address)
122 {
123         u_char i,j,found = 0;
124 
125         if (xd_override)
126         {
127                 *controller = xd_type;
128                 *address = NULL;
129                 return(1);
130         }
131 
132         for (i = 0; i < (sizeof(xd_bases) / sizeof(xd_bases[0])) && !found; i++)
133                 for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])) && !found; j++)
134                         if (!memcmp(xd_bases[i] + xd_sigs[j].offset,xd_sigs[j].string,strlen(xd_sigs[j].string))) {
135                                 *controller = j;
136                                 *address = xd_bases[i];
137                                 found++;
138                         }
139         return (found);
140 }
141 
142 /* xd_geninit: set up the "raw" device entries in the table */
143 static void xd_geninit (void)
144 {
145         u_char i;
146 
147         for (i = 0; i < xd_drives; i++) {
148                 xd[i << 6].nr_sects = xd_info[i].heads * xd_info[i].cylinders * xd_info[i].sectors;
149                 xd_valid[i] = 1;
150         }
151 
152         xd_gendisk.nr_real = xd_drives;
153 
154         for(i=0;i<(XD_MAXDRIVES << 6);i++) xd_blocksizes[i] = 1024;
155         blksize_size[MAJOR_NR] = xd_blocksizes;
156 }
157 
158 /* xd_open: open a device */
159 static int xd_open (struct inode *inode,struct file *file)
160 {
161         int dev = DEVICE_NR(MINOR(inode->i_rdev));
162 
163         if (dev < xd_drives) {
164                 while (!xd_valid[dev])
165                         sleep_on(&xd_wait_open);
166 
167                 xd_access[dev]++;
168 
169                 return (0);
170         }
171         else
172                 return (-ENODEV);
173 }
174 
175 /* do_xd_request: handle an incoming request */
176 static void do_xd_request (void)
177 {
178         u_int block,count,retry;
179         int code;
180 
181         sti();
182         while (code = 0, CURRENT) {
183                 INIT_REQUEST;   /* do some checking on the request structure */
184 
185                 if (CURRENT_DEV < xd_drives && CURRENT->sector + CURRENT->nr_sectors <= xd[MINOR(CURRENT->dev)].nr_sects) {
186                         block = CURRENT->sector + xd[MINOR(CURRENT->dev)].start_sect;
187                         count = CURRENT->nr_sectors;
188 
189                         switch (CURRENT->cmd) {
190                                 case READ:
191                                 case WRITE:     for (retry = 0; (retry < XD_RETRIES) && !code; retry++)
192                                                         code = xd_readwrite(CURRENT->cmd,CURRENT_DEV,CURRENT->buffer,block,count);
193                                                 break;
194                                 default:        printk("do_xd_request: unknown request\n"); break;
195                         }
196                 }
197                 end_request(code);      /* wrap up, 0 = fail, 1 = success */
198         }
199 }
200 
201 /* xd_ioctl: handle device ioctl's */
202 static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
203 {
204         XD_GEOMETRY *geometry = (XD_GEOMETRY *) arg;
205         int dev = DEVICE_NR(MINOR(inode->i_rdev)),err;
206 
207         if (inode && (dev < xd_drives))
208                 switch (cmd) {
209                         case HDIO_GETGEO:       if (arg) {
210                                                         if ((err = verify_area(VERIFY_WRITE,geometry,sizeof(*geometry))))
211                                                                 return (err);
212                                                         put_fs_byte(xd_info[dev].heads,(char *) &geometry->heads);
213                                                         put_fs_byte(xd_info[dev].sectors,(char *) &geometry->sectors);
214                                                         put_fs_word(xd_info[dev].cylinders,(short *) &geometry->cylinders);
215                                                         put_fs_long(xd[MINOR(inode->i_rdev)].start_sect,(long *) &geometry->start);
216 
217                                                         return (0);
218                                                 }
219                                                 break;
220                         case BLKGETSIZE:        if (arg) {
221                                                         if ((err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long))))
222                                                                 return (err);
223                                                         put_fs_long(xd[MINOR(inode->i_rdev)].nr_sects,(long *) arg);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -