2 * This file contains the driver for an XT hard disk controller (at least the DTC 5150X) for Linux.
4 * Author: Pat Mackinlay, smackinla@cc.curtin.edu.au
7 * Revised: 01/01/93, ...
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.
14 #include <linux/errno.h>
15 #include <linux/sched.h>
17 #include <linux/kernel.h>
18 #include <linux/genhd.h>
21 #include <asm/system.h>
23 #include <asm/segment.h>
26 #define MAJOR_NR XT_DISK_MAJOR
29 XD_INFO xd_info
[XD_MAXDRIVES
];
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:
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:
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
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>.
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"). */
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 */
64 static u_char
*xd_bases
[] =
66 (u_char
*) 0xC8000,(u_char
*) 0xCA000,(u_char
*) 0xCC000,
67 (u_char
*) 0xCE000,(u_char
*) 0xD0000,(u_char
*) 0xD8000,
71 static struct hd_struct xd
[XD_MAXDRIVES
<< 6];
72 static int xd_sizes
[XD_MAXDRIVES
<< 6],xd_access
[XD_MAXDRIVES
] = { 0,0 };
73 static int xd_blocksizes
[XD_MAXDRIVES
<< 6];
74 static struct gendisk xd_gendisk
= { MAJOR_NR
,"xd",6,1 << 6,XD_MAXDRIVES
,xd_geninit
,xd
,xd_sizes
,0,(void *) xd_info
,NULL
};
75 static struct file_operations xd_fops
= { NULL
,block_read
,block_write
,NULL
,NULL
,xd_ioctl
,NULL
,xd_open
,xd_release
,block_fsync
};
77 static struct wait_queue
*xd_wait_int
= NULL
,*xd_wait_open
= NULL
;
78 static u_char xd_valid
[XD_MAXDRIVES
] = { 0,0 };
79 static u_char xd_drives
= 0,xd_irq
= 0,xd_dma
= 0,xd_maxsectors
,xd_override
= 0,xd_type
= 0;
80 static u_short xd_iobase
= 0;
82 /* xd_init: grab the IRQ and DMA channel and initialise the drives */
83 u_long
xd_init (u_long mem_start
,u_long mem_end
)
85 u_char i
,controller
,*address
;
87 if (register_blkdev(MAJOR_NR
,"xd",&xd_fops
)) {
88 printk("xd_init: unable to get major number %d\n",MAJOR_NR
);
91 blk_dev
[MAJOR_NR
].request_fn
= DEVICE_REQUEST
;
92 read_ahead
[MAJOR_NR
] = 8; /* 8 sector (4kB) read ahead */
93 xd_gendisk
.next
= gendisk_head
;
94 gendisk_head
= &xd_gendisk
;
96 if (xd_detect(&controller
,&address
)) {
98 printk("xd_init: detected a%s controller (type %d) at address %p\n",xd_sigs
[controller
].name
,controller
,address
);
100 xd_sigs
[controller
].init_controller(address
);
101 xd_drives
= xd_initdrives(xd_sigs
[controller
].init_drive
);
103 printk("xd_init: detected %d hard drive%s (using IRQ%d & DMA%d)\n",xd_drives
,xd_drives
== 1 ? "" : "s",xd_irq
,xd_dma
);
104 for (i
= 0; i
< xd_drives
; i
++)
105 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 if (!request_irq(xd_irq
,xd_interrupt_handler
)) {
108 if (request_dma(xd_dma
)) {
109 printk("xd_init: unable to get DMA%d\n",xd_dma
);
114 printk("xd_init: unable to get IRQ%d\n",xd_irq
);
119 /* xd_detect: scan the possible BIOS ROM locations for the signature strings */
120 static u_char
xd_detect (u_char
*controller
,u_char
**address
)
122 u_char i
,j
,found
= 0;
126 *controller
= xd_type
;
131 for (i
= 0; i
< (sizeof(xd_bases
) / sizeof(xd_bases
[0])) && !found
; i
++)
132 for (j
= 1; j
< (sizeof(xd_sigs
) / sizeof(xd_sigs
[0])) && !found
; j
++)
133 if (!memcmp(xd_bases
[i
] + xd_sigs
[j
].offset
,xd_sigs
[j
].string
,strlen(xd_sigs
[j
].string
))) {
135 *address
= xd_bases
[i
];
141 /* xd_geninit: set up the "raw" device entries in the table */
142 static void xd_geninit (void)
146 for (i
= 0; i
< xd_drives
; i
++) {
147 xd
[i
<< 6].nr_sects
= xd_info
[i
].heads
* xd_info
[i
].cylinders
* xd_info
[i
].sectors
;
151 xd_gendisk
.nr_real
= xd_drives
;
153 for(i
=0;i
<(XD_MAXDRIVES
<< 6);i
++) xd_blocksizes
[i
] = 1024;
154 blksize_size
[MAJOR_NR
] = xd_blocksizes
;
157 /* xd_open: open a device */
158 static int xd_open (struct inode
*inode
,struct file
*file
)
160 int dev
= DEVICE_NR(MINOR(inode
->i_rdev
));
162 if (dev
< xd_drives
) {
163 while (!xd_valid
[dev
])
164 sleep_on(&xd_wait_open
);
174 /* do_xd_request: handle an incoming request */
175 static void do_xd_request (void)
177 u_int block
,count
,retry
;
181 while (code
= 0, CURRENT
) {
182 INIT_REQUEST
; /* do some checking on the request structure */
184 if (CURRENT_DEV
< xd_drives
&& CURRENT
->sector
+ CURRENT
->nr_sectors
<= xd
[MINOR(CURRENT
->dev
)].nr_sects
) {
185 block
= CURRENT
->sector
+ xd
[MINOR(CURRENT
->dev
)].start_sect
;
186 count
= CURRENT
->nr_sectors
;
188 switch (CURRENT
->cmd
) {
190 case WRITE
: for (retry
= 0; (retry
< XD_RETRIES
) && !code
; retry
++)
191 code
= xd_readwrite(CURRENT
->cmd
,CURRENT_DEV
,CURRENT
->buffer
,block
,count
);
193 default: printk("do_xd_request: unknown request\n"); break;
196 end_request(code
); /* wrap up, 0 = fail, 1 = success */
200 /* xd_ioctl: handle device ioctl's */
201 static int xd_ioctl (struct inode
*inode
,struct file
*file
,u_int cmd
,u_long arg
)
203 XD_GEOMETRY
*geometry
= (XD_GEOMETRY
*) arg
;
204 int dev
= DEVICE_NR(MINOR(inode
->i_rdev
)),err
;
206 if (inode
&& (dev
< xd_drives
))
208 case HDIO_GETGEO
: if (arg
) {
209 if ((err
= verify_area(VERIFY_WRITE
,geometry
,sizeof(*geometry
))))
211 put_fs_byte(xd_info
[dev
].heads
,(char *) &geometry
->heads
);
212 put_fs_byte(xd_info
[dev
].sectors
,(char *) &geometry
->sectors
);
213 put_fs_word(xd_info
[dev
].cylinders
,(short *) &geometry
->cylinders
);
214 put_fs_long(xd
[MINOR(inode
->i_rdev
)].start_sect
,(long *) &geometry
->start
);
219 case BLKGETSIZE
: if (arg
) {
220 if ((err
= verify_area(VERIFY_WRITE
,(long *) arg
,sizeof(long))))
222 put_fs_long(xd
[MINOR(inode
->i_rdev
)].nr_sects
,(long *) arg
);
228 if(!suser()) return -EACCES
;
229 if(!inode
->i_rdev
) return -EINVAL
;
230 fsync_dev(inode
->i_rdev
);
231 invalidate_buffers(inode
->i_rdev
);
234 case BLKRRPART
: return (xd_reread_partitions(inode
->i_rdev
));
235 RO_IOCTLS(inode
->i_rdev
,arg
);
240 /* xd_release: release the device */
241 static void xd_release (struct inode
*inode
, struct file
*file
)
243 int dev
= DEVICE_NR(MINOR(inode
->i_rdev
));
245 if (dev
< xd_drives
) {
251 /* xd_reread_partitions: rereads the partition table from a drive */
252 static int xd_reread_partitions(int dev
)
254 int target
= DEVICE_NR(MINOR(dev
)),start
= target
<< xd_gendisk
.minor_shift
,partition
;
256 cli(); xd_valid
[target
] = (xd_access
[target
] != 1); sti();
257 if (xd_valid
[target
])
260 for (partition
= xd_gendisk
.max_p
- 1; partition
>= 0; partition
--) {
261 sync_dev(MAJOR_NR
<< 8 | start
| partition
);
262 invalidate_inodes(MAJOR_NR
<< 8 | start
| partition
);
263 invalidate_buffers(MAJOR_NR
<< 8 | start
| partition
);
264 xd_gendisk
.part
[start
+ partition
].start_sect
= 0;
265 xd_gendisk
.part
[start
+ partition
].nr_sects
= 0;
268 xd_gendisk
.part
[start
].nr_sects
= xd_info
[target
].heads
* xd_info
[target
].cylinders
* xd_info
[target
].sectors
;
269 resetup_one_dev(&xd_gendisk
,target
);
271 xd_valid
[target
] = 1;
272 wake_up(&xd_wait_open
);
277 /* xd_readwrite: handle a read/write request */
278 static int xd_readwrite (u_char operation
,u_char drive
,char *buffer
,u_int block
,u_int count
)
280 u_char cmdblk
[6],sense
[4];
281 u_short track
,cylinder
;
282 u_char head
,sector
,control
,mode
,temp
;
284 #ifdef DEBUG_READWRITE
285 printk("xd_readwrite: operation = %s, drive = %d, buffer = 0x%X, block = %d, count = %d\n",operation
== READ
? "read" : "write",drive
,buffer
,block
,count
);
286 #endif /* DEBUG_READWRITE */
288 control
= xd_info
[drive
].control
;
290 temp
= count
< xd_maxsectors
? count
: xd_maxsectors
;
292 track
= block
/ xd_info
[drive
].sectors
;
293 head
= track
% xd_info
[drive
].heads
;
294 cylinder
= track
/ xd_info
[drive
].heads
;
295 sector
= block
% xd_info
[drive
].sectors
;
297 #ifdef DEBUG_READWRITE
298 printk("xd_readwrite: drive = %d, head = %d, cylinder = %d, sector = %d, count = %d\n",drive
,head
,cylinder
,sector
,temp
);
299 #endif /* DEBUG_READWRITE */
301 mode
= xd_setup_dma(operation
== READ
? DMA_MODE_READ
: DMA_MODE_WRITE
,(u_char
*)buffer
,temp
* 0x200);
302 xd_build(cmdblk
,operation
== READ
? CMD_READ
: CMD_WRITE
,drive
,head
,cylinder
,sector
,temp
& 0xFF,control
);
304 switch (xd_command(cmdblk
,mode
,(u_char
*) buffer
,(u_char
*) buffer
,sense
,XD_TIMEOUT
)) {
305 case 1: printk("xd_readwrite: timeout, recalibrating drive\n"); xd_recalibrate(drive
); return (0);
306 case 2: switch ((sense
[0] & 0x30) >> 4) {
307 case 0: printk("xd_readwrite: drive error, code = 0x%X",sense
[0] & 0x0F); break;
308 case 1: printk("xd_readwrite: controller error, code = 0x%X",sense
[0] & 0x0F); break;
309 case 2: printk("xd_readwrite: command error, code = 0x%X",sense
[0] & 0x0F); break;
310 case 3: printk("xd_readwrite: miscellaneous error, code = 0x%X",sense
[0] & 0x0F); break;
313 printk(" - drive = %d, head = %d, cylinder = %d, sector = %d\n",sense
[1] & 0xE0,sense
[1] & 0x1F,((sense
[2] & 0xC0) << 2) | sense
[3],sense
[2] & 0x3F);
315 printk(" - no valid disk address\n");
318 count
-= temp
, buffer
+= temp
* 0x200, block
+= temp
;
323 /* xd_recalibrate: recalibrate a given drive and reset controller if necessary */
324 static void xd_recalibrate (u_char drive
)
328 xd_build(cmdblk
,CMD_RECALIBRATE
,drive
,0,0,0,0,0);
329 if (xd_command(cmdblk
,PIO_MODE
,0,0,0,XD_TIMEOUT
* 8))
330 printk("xd_recalibrate: warning! error recalibrating, controller may be unstable\n");
333 /* xd_interrupt_handler: interrupt service routine */
334 static void xd_interrupt_handler (int unused
)
336 if (inb(XD_STATUS
) & STAT_INTERRUPT
) { /* check if it was our device */
338 printk("xd_interrupt_handler: interrupt detected\n");
339 #endif /* DEBUG_OTHER */
340 outb(0,XD_CONTROL
); /* acknowledge interrupt */
341 wake_up(&xd_wait_int
); /* and wake up sleeping processes */
344 printk("xd_interrupt_handler: unexpected interrupt\n");
347 /* xd_dma: set up the DMA controller for a data transfer */
348 static u_char
xd_setup_dma (u_char mode
,u_char
*buffer
,u_int count
)
350 if (buffer
< ((u_char
*) 0x1000000 - count
)) { /* transfer to address < 16M? */
351 if (((u_int
) buffer
& 0xFFFF0000) != ((u_int
) buffer
+ count
) & 0xFFFF0000) {
353 printk("xd_setup_dma: using PIO, transfer overlaps 64k boundary\n");
354 #endif /* DEBUG_OTHER */
358 clear_dma_ff(xd_dma
);
359 set_dma_mode(xd_dma
,mode
);
360 set_dma_addr(xd_dma
,(u_int
) buffer
);
361 set_dma_count(xd_dma
,count
);
363 return (DMA_MODE
); /* use DMA and INT */
366 printk("xd_setup_dma: using PIO, cannot DMA above 16 meg\n");
367 #endif /* DEBUG_OTHER */
371 /* xd_build: put stuff into an array in a format suitable for the controller */
372 static u_char
*xd_build (u_char
*cmdblk
,u_char command
,u_char drive
,u_char head
,u_short cylinder
,u_char sector
,u_char count
,u_char control
)
375 cmdblk
[1] = ((drive
& 0x07) << 5) | (head
& 0x1F);
376 cmdblk
[2] = ((cylinder
& 0x300) >> 2) | (sector
& 0x3F);
377 cmdblk
[3] = cylinder
& 0xFF;
384 /* xd_waitport: waits until port & mask == flags or a timeout occurs. return 1 for a timeout */
385 static inline u_char
xd_waitport (u_short port
,u_char flags
,u_char mask
,u_long timeout
)
387 u_long expiry
= jiffies
+ timeout
;
389 while (((inb(port
) & mask
) != flags
) && (jiffies
< expiry
))
392 return (jiffies
>= expiry
);
395 /* xd_command: handle all data transfers necessary for a single command */
396 static u_int
xd_command (u_char
*command
,u_char mode
,u_char
*indata
,u_char
*outdata
,u_char
*sense
,u_long timeout
)
398 u_char cmdblk
[6],csb
,complete
= 0;
401 printk("xd_command: command = 0x%X, mode = 0x%X, indata = 0x%X, outdata = 0x%X, sense = 0x%X\n",command
,mode
,indata
,outdata
,sense
);
402 #endif /* DEBUG_COMMAND */
405 outb(mode
,XD_CONTROL
);
407 if (xd_waitport(XD_STATUS
,STAT_SELECT
,STAT_SELECT
,timeout
))
411 if (xd_waitport(XD_STATUS
,STAT_READY
,STAT_READY
,timeout
))
413 switch (inb(XD_STATUS
) & (STAT_COMMAND
| STAT_INPUT
)) {
414 case 0: if (mode
== DMA_MODE
) {
416 sleep_on(&xd_wait_int
);
420 outb(outdata
? *outdata
++ : 0,XD_DATA
);
422 case STAT_INPUT
: if (mode
== DMA_MODE
) {
424 sleep_on(&xd_wait_int
);
429 *indata
++ = inb(XD_DATA
);
433 case STAT_COMMAND
: outb(command
? *command
++ : 0,XD_DATA
); break;
435 | STAT_INPUT
: complete
= 1; break;
440 if (xd_waitport(XD_STATUS
,0,STAT_SELECT
,timeout
)) /* wait until deselected */
443 if (csb
& CSB_ERROR
) { /* read sense data if error */
444 xd_build(cmdblk
,CMD_SENSE
,(csb
& CSB_LUN
) >> 5,0,0,0,0,0);
445 if (xd_command(cmdblk
,0,sense
,0,0,XD_TIMEOUT
))
446 printk("xd_command: warning! sense command failed!\n");
450 printk("xd_command: completed with csb = 0x%X\n",csb
);
451 #endif /* DEBUG_COMMAND */
453 return (csb
& CSB_ERROR
);
456 static u_char
xd_initdrives (void (*init_drive
)(u_char drive
))
458 u_char cmdblk
[6],i
,count
= 0;
460 for (i
= 0; i
< XD_MAXDRIVES
; i
++) {
461 xd_build(cmdblk
,CMD_TESTREADY
,i
,0,0,0,0,0);
462 if (!xd_command(cmdblk
,PIO_MODE
,0,0,0,XD_TIMEOUT
* 2)) {
470 static void xd_dtc_init_controller (u_char
*address
)
472 switch ((u_long
) address
) {
473 case 0xC8000: xd_iobase
= 0x320; break;
474 case 0xCA000: xd_iobase
= 0x324; break;
475 default: printk("xd_dtc_init_controller: unsupported BIOS address %p\n",address
);
476 xd_iobase
= 0x320; break;
478 xd_irq
= 5; /* the IRQ _can_ be changed on this card, but requires a hardware mod */
480 xd_maxsectors
= 0x01; /* my card seems to have trouble doing multi-block transfers? */
482 outb(0,XD_RESET
); /* reset the controller */
485 static void xd_dtc_init_drive (u_char drive
)
487 u_char cmdblk
[6],buf
[64];
489 xd_build(cmdblk
,CMD_DTCGETGEOM
,drive
,0,0,0,0,0);
490 if (!xd_command(cmdblk
,PIO_MODE
,buf
,0,0,XD_TIMEOUT
* 2)) {
491 xd_info
[drive
].heads
= buf
[0x0A]; /* heads */
492 xd_info
[drive
].cylinders
= ((u_short
*) (buf
))[0x04]; /* cylinders */
493 xd_info
[drive
].sectors
= 17; /* sectors */
495 xd_info
[drive
].rwrite
= ((u_short
*) (buf
+ 1))[0x05]; /* reduced write */
496 xd_info
[drive
].precomp
= ((u_short
*) (buf
+ 1))[0x06]; /* write precomp */
497 xd_info
[drive
].ecc
= buf
[0x0F]; /* ecc length */
499 xd_info
[drive
].control
= 0; /* control byte */
501 xd_setparam(CMD_DTCSETPARAM
,drive
,xd_info
[drive
].heads
,xd_info
[drive
].cylinders
,((u_short
*) (buf
+ 1))[0x05],((u_short
*) (buf
+ 1))[0x06],buf
[0x0F]);
502 xd_build(cmdblk
,CMD_DTCSETSTEP
,drive
,0,0,0,0,7);
503 if (xd_command(cmdblk
,PIO_MODE
,0,0,0,XD_TIMEOUT
* 2))
504 printk("xd_dtc_init_drive: error setting step rate for drive %d\n",drive
);
507 printk("xd_dtc_init_drive: error reading geometry for drive %d\n",drive
);
510 static void xd_wd_init_controller (u_char
*address
)
512 switch ((u_long
) address
) {
513 case 0xC8000: xd_iobase
= 0x320; break;
514 case 0xCA000: xd_iobase
= 0x324; break;
515 case 0xCC000: xd_iobase
= 0x328; break;
516 case 0xCE000: xd_iobase
= 0x32C; break;
517 case 0xD0000: xd_iobase
= 0x328; break;
518 case 0xD8000: xd_iobase
= 0x32C; break;
519 default: printk("xd_wd_init_controller: unsupported BIOS address %p\n",address
);
520 xd_iobase
= 0x320; break;
522 xd_irq
= 5; /* don't know how to auto-detect this yet */
524 xd_maxsectors
= 0x01; /* this one doesn't wrap properly either... */
526 /* outb(0,XD_RESET); */ /* reset the controller */
529 static void xd_wd_init_drive (u_char drive
)
531 u_char cmdblk
[6],buf
[0x200];
533 xd_build(cmdblk
,CMD_READ
,drive
,0,0,0,1,0);
534 if (!xd_command(cmdblk
,PIO_MODE
,buf
,0,0,XD_TIMEOUT
* 2)) {
535 xd_info
[drive
].heads
= buf
[0x1AF]; /* heads */
536 xd_info
[drive
].cylinders
= ((u_short
*) (buf
+ 1))[0xD6]; /* cylinders */
537 xd_info
[drive
].sectors
= 17; /* sectors */
539 xd_info
[drive
].rwrite
= ((u_short
*) (buf
))[0xD8]; /* reduced write */
540 xd_info
[drive
].wprecomp
= ((u_short
*) (buf
))[0xDA]; /* write precomp */
541 xd_info
[drive
].ecc
= buf
[0x1B4]; /* ecc length */
543 xd_info
[drive
].control
= buf
[0x1B5]; /* control byte */
545 xd_setparam(CMD_WDSETPARAM
,drive
,xd_info
[drive
].heads
,xd_info
[drive
].cylinders
,((u_short
*) (buf
))[0xD8],((u_short
*) (buf
))[0xDA],buf
[0x1B4]);
548 printk("xd_wd_init_drive: error reading geometry for drive %d\n",drive
);
551 static void xd_seagate_init_controller (u_char
*address
)
553 switch ((u_long
) address
) {
554 case 0xC8000: xd_iobase
= 0x320; break;
555 case 0xD0000: xd_iobase
= 0x324; break;
556 case 0xD8000: xd_iobase
= 0x328; break;
557 case 0xE0000: xd_iobase
= 0x32C; break;
558 default: printk("xd_seagate_init_controller: unsupported BIOS address %p\n",address
);
559 xd_iobase
= 0x320; break;
561 xd_irq
= 5; /* the IRQ and DMA channel are fixed on the Seagate controllers */
563 xd_maxsectors
= 0x40;
565 outb(0,XD_RESET
); /* reset the controller */
568 static void xd_seagate_init_drive (u_char drive
)
570 u_char cmdblk
[6],buf
[0x200];
572 xd_build(cmdblk
,CMD_ST11GETGEOM
,drive
,0,0,0,1,0);
573 if (!xd_command(cmdblk
,PIO_MODE
,buf
,0,0,XD_TIMEOUT
* 2)) {
574 xd_info
[drive
].heads
= buf
[0x04]; /* heads */
575 xd_info
[drive
].cylinders
= (buf
[0x02] << 8) | buf
[0x03]; /* cylinders */
576 xd_info
[drive
].sectors
= buf
[0x05]; /* sectors */
577 xd_info
[drive
].control
= 0; /* control byte */
580 printk("xd_seagate_init_drive: error reading geometry from drive %d\n",drive
);
583 /* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads
584 etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */
585 static void xd_override_init_drive (u_char drive
)
587 u_short min
[] = { 0,0,0 },max
[] = { 16,1024,64 },test
[] = { 0,0,0 };
590 for (i
= 0; i
< 3; i
++) {
591 while (min
[i
] != max
[i
] - 1) {
592 test
[i
] = (min
[i
] + max
[i
]) / 2;
593 xd_build(cmdblk
,CMD_SEEK
,drive
,(u_char
) test
[0],(u_short
) test
[1],(u_char
) test
[2],0,0);
594 if (!xd_command(cmdblk
,PIO_MODE
,0,0,0,XD_TIMEOUT
* 2))
601 xd_info
[drive
].heads
= (u_char
) min
[0] + 1;
602 xd_info
[drive
].cylinders
= (u_short
) min
[1] + 1;
603 xd_info
[drive
].sectors
= (u_char
) min
[2] + 1;
604 xd_info
[drive
].control
= 0;
607 /* xd_setup: initialise from command line parameters */
608 void xd_setup (char *command
,int *integers
)
612 xd_type
= integers
[1];
613 xd_irq
= integers
[2];
614 xd_iobase
= integers
[3];
615 xd_dma
= integers
[4];
617 xd_maxsectors
= 0x01;
620 /* xd_setparam: set the drive characteristics */
621 static void xd_setparam (u_char command
,u_char drive
,u_char heads
,u_short cylinders
,u_short rwrite
,u_short wprecomp
,u_char ecc
)
625 xd_build(cmdblk
,command
,drive
,0,0,0,0,0);
626 cmdblk
[6] = (u_char
) (cylinders
>> 8) & 0x03;
627 cmdblk
[7] = (u_char
) (cylinders
& 0xFF);
628 cmdblk
[8] = heads
& 0x1F;
629 cmdblk
[9] = (u_char
) (rwrite
>> 8) & 0x03;
630 cmdblk
[10] = (u_char
) (rwrite
& 0xFF);
631 cmdblk
[11] = (u_char
) (wprecomp
>> 8) & 0x03;
632 cmdblk
[12] = (u_char
) (wprecomp
& 0xFF);
635 if (xd_command(cmdblk
,PIO_MODE
,0,0,0,XD_TIMEOUT
* 2))
636 printk("xd_setparam: error setting characteristics for drive %d\n",drive
);