OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [block/] [ps2esdi.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* ps2esdi driver based on assembler code by Arindam Banerji,
2
   written by Peter De Schrijver */
3
/* Reassuring note to IBM : This driver was NOT developed by vice-versa
4
   engineering the PS/2's BIOS */
5
/* Dedicated to Wannes, Tofke, Ykke, Godot, Killroy and all those
6
   other lovely fish out there... */
7
/* This code was written during the long and boring WINA
8
   elections 1994 */
9
/* Thanks to Arindam Banerij for giving me the source of his driver */
10
/* This code may be freely distributed and modified in any way,
11
   as long as these notes remain intact */
12
 
13
/*  Revised: 05/07/94 by Arindam Banerji (axb@cse.nd.edu) */
14
/*  Revised: 09/08/94 by Peter De Schrijver (stud11@cc4.kuleuven.ac.be)
15
   Thanks to Arindam Banerij for sending me the docs of the adapter */
16
 
17
/* BA Modified for ThinkPad 720 by Boris Ashkinazi */
18
/*                    (bash@vnet.ibm.com) 08/08/95 */
19
 
20
/* Modified further for ThinkPad-720C by Uri Blumenthal */
21
/*                    (uri@watson.ibm.com) Sep 11, 1995 */
22
 
23
/* TODO :
24
   + Timeouts
25
   + Get disk parameters
26
   + DMA above 16MB
27
   + reset after read/write error
28
 */
29
 
30
#include <linux/config.h>
31
#include <linux/major.h>
32
 
33
#ifdef  CONFIG_BLK_DEV_PS2
34
 
35
#define MAJOR_NR PS2ESDI_MAJOR
36
 
37
#include <linux/errno.h>
38
#include <linux/sched.h>
39
#include <linux/mm.h>
40
#include <linux/fs.h>
41
#include <linux/kernel.h>
42
#include <linux/genhd.h>
43
#include <linux/ps2esdi.h>
44
#include <linux/devfs_fs_kernel.h>
45
#include <linux/blk.h>
46
#include <linux/blkpg.h>
47
#include <linux/mca.h>
48
#include <linux/init.h>
49
#include <linux/ioport.h>
50
#include <linux/module.h>
51
 
52
#include <asm/system.h>
53
#include <asm/io.h>
54
#include <asm/segment.h>
55
#include <asm/dma.h>
56
#include <asm/mca_dma.h>
57
#include <asm/uaccess.h>
58
 
59
#define PS2ESDI_IRQ 14
60
#define MAX_HD 2
61
#define MAX_RETRIES 5
62
#define MAX_16BIT 65536
63
#define ESDI_TIMEOUT   0xf000
64
#define ESDI_STAT_TIMEOUT 4
65
 
66
#define TYPE_0_CMD_BLK_LENGTH 2
67
#define TYPE_1_CMD_BLK_LENGTH 4
68
 
69
 
70
static void reset_ctrl(void);
71
 
72
int ps2esdi_init(void);
73
 
74
static void ps2esdi_geninit(void);
75
 
76
static void do_ps2esdi_request(request_queue_t * q);
77
 
78
static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count);
79
 
80
static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
81
u_short cyl, u_short head, u_short sector, u_short length, u_char drive);
82
 
83
static int ps2esdi_out_cmd_blk(u_short * cmd_blk);
84
 
85
static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode);
86
 
87
static void ps2esdi_interrupt_handler(int irq, void *dev_id,
88
                                      struct pt_regs *regs);
89
static void (*current_int_handler) (u_int) = NULL;
90
static void ps2esdi_normal_interrupt_handler(u_int);
91
static void ps2esdi_initial_reset_int_handler(u_int);
92
static void ps2esdi_geometry_int_handler(u_int);
93
 
94
static int ps2esdi_open(struct inode *inode, struct file *file);
95
 
96
static int ps2esdi_release(struct inode *inode, struct file *file);
97
 
98
static int ps2esdi_ioctl(struct inode *inode, struct file *file,
99
                         u_int cmd, u_long arg);
100
 
101
static int ps2esdi_reread_partitions(kdev_t dev);
102
 
103
static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
104
 
105
static void dump_cmd_complete_status(u_int int_ret_code);
106
 
107
static void ps2esdi_get_device_cfg(void);
108
 
109
static void ps2esdi_reset_timer(unsigned long unused);
110
 
111
static u_int dma_arb_level;             /* DMA arbitration level */
112
 
113
static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
114
static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_wait_open);
115
 
116
static int no_int_yet;
117
static int access_count[MAX_HD];
118
static char ps2esdi_valid[MAX_HD];
119
static int ps2esdi_sizes[MAX_HD << 6];
120
static int ps2esdi_blocksizes[MAX_HD << 6];
121
static int ps2esdi_maxsect[MAX_HD << 6];
122
static int ps2esdi_drives;
123
static struct hd_struct ps2esdi[MAX_HD << 6];
124
static u_short io_base;
125
static struct timer_list esdi_timer = { function: ps2esdi_reset_timer };
126
static int reset_status;
127
static int ps2esdi_slot = -1;
128
static int tp720esdi = 0;        /* Is it Integrated ESDI of ThinkPad-720? */
129
static int intg_esdi = 0;       /* If integrated adapter */
130
struct ps2esdi_i_struct {
131
        unsigned int head, sect, cyl, wpcom, lzone, ctl;
132
};
133
 
134
#if 0
135
#if 0                           /* try both - I don't know which one is better... UB */
136
static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
137
{
138
        {4, 48, 1553, 0, 0, 0},
139
        {0, 0, 0, 0, 0, 0}};
140
#else
141
static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
142
{
143
        {64, 32, 161, 0, 0, 0},
144
        {0, 0, 0, 0, 0, 0}};
145
#endif
146
#endif
147
static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
148
{
149
        {0, 0, 0, 0, 0, 0},
150
        {0, 0, 0, 0, 0, 0}};
151
 
152
static struct block_device_operations ps2esdi_fops =
153
{
154
        owner:          THIS_MODULE,
155
        open:           ps2esdi_open,
156
        release:        ps2esdi_release,
157
        ioctl:          ps2esdi_ioctl,
158
};
159
 
160
static struct gendisk ps2esdi_gendisk =
161
{
162
        major:          MAJOR_NR,
163
        major_name:     "ed",
164
        minor_shift:    6,
165
        max_p:          1 << 6,
166
        part:           ps2esdi,
167
        sizes:          ps2esdi_sizes,
168
        real_devices:   (void *)ps2esdi_info,
169
        fops:           &ps2esdi_fops,
170
};
171
 
172
/* initialization routine called by ll_rw_blk.c   */
173
int __init ps2esdi_init(void)
174
{
175
 
176
        /* register the device - pass the name, major number and operations
177
           vector .                                                 */
178
        if (devfs_register_blkdev(MAJOR_NR, "ed", &ps2esdi_fops)) {
179
                printk("%s: Unable to get major number %d\n", DEVICE_NAME, MAJOR_NR);
180
                return -1;
181
        }
182
        /* set up some global information - indicating device specific info */
183
        blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
184
        read_ahead[MAJOR_NR] = 8;       /* 8 sector (4kB) read ahead */
185
 
186
        /* some minor housekeeping - setup the global gendisk structure */
187
        add_gendisk(&ps2esdi_gendisk);
188
        ps2esdi_geninit();
189
        return 0;
190
}                               /* ps2esdi_init */
191
 
192
#ifdef MODULE
193
 
194
static int cyl[MAX_HD] = {-1,-1};
195
static int head[MAX_HD] = {-1, -1};
196
static int sect[MAX_HD] = {-1, -1};
197
 
198
MODULE_PARM(tp720esdi, "i");
199
MODULE_PARM(cyl, "i");
200
MODULE_PARM(head, "i");
201
MODULE_PARM(track, "i");
202
MODULE_LICENSE("GPL");
203
 
204
int init_module(void) {
205
        int drive;
206
 
207
        for(drive = 0; drive < MAX_HD; drive++) {
208
                struct ps2_esdi_i_struct *info = &ps2esdi_info[drive];
209
 
210
                if (cyl[drive] != -1) {
211
                        info->cyl = info->lzone = cyl[drive];
212
                        info->wpcom = 0;
213
                }
214
                if (head[drive] != -1) {
215
                        info->head = head[drive];
216
                        info->ctl = (head[drive] > 8 ? 8 : 0);
217
                }
218
                if (sect[drive] != -1) info->sect = sect[drive];
219
        }
220
        return ps2esdi_init();
221
}
222
 
223
void
224
cleanup_module(void)
225
{
226
        if(ps2esdi_slot) {
227
                mca_mark_as_unused(ps2esdi_slot);
228
                mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
229
        }
230
        release_region(io_base, 4);
231
        free_dma(dma_arb_level);
232
        free_irq(PS2ESDI_IRQ, NULL);
233
        devfs_unregister_blkdev(MAJOR_NR, "ed");
234
        del_gendisk(&ps2esdi_gendisk);
235
        blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
236
}
237
#endif /* MODULE */
238
 
239
/* handles boot time command line parameters */
240
void __init tp720_setup(char *str, int *ints)
241
{
242
        /* no params, just sets the tp720esdi flag if it exists */
243
 
244
        printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME);
245
        tp720esdi = 1;
246
}
247
 
248
void __init ed_setup(char *str, int *ints)
249
{
250
        int hdind = 0;
251
 
252
        /* handles 3 parameters only - corresponding to
253
           1. Number of cylinders
254
           2. Number of heads
255
           3. Sectors/track
256
         */
257
 
258
        if (ints[0] != 3)
259
                return;
260
 
261
        /* print out the information - seen at boot time */
262
        printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n",
263
               DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]);
264
 
265
        /* set the index into device specific information table */
266
        if (ps2esdi_info[0].head != 0)
267
                hdind = 1;
268
 
269
        /* set up all the device information */
270
        ps2esdi_info[hdind].head = ints[2];
271
        ps2esdi_info[hdind].sect = ints[3];
272
        ps2esdi_info[hdind].cyl = ints[1];
273
        ps2esdi_info[hdind].wpcom = 0;
274
        ps2esdi_info[hdind].lzone = ints[1];
275
        ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
276
#if 0                           /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */
277
        ps2esdi_drives = hdind + 1;     /* increment index for the next time */
278
#endif
279
}                               /* ed_setup */
280
 
281
static int ps2esdi_getinfo(char *buf, int slot, void *d)
282
{
283
        int len = 0;
284
 
285
        len += sprintf(buf + len, "DMA Arbitration Level: %d\n",
286
                       dma_arb_level);
287
        len += sprintf(buf + len, "IO Port: %x\n", io_base);
288
        len += sprintf(buf + len, "IRQ: 14\n");
289
        len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives);
290
 
291
        return len;
292
}
293
 
294
/* ps2 esdi specific initialization - called thru the gendisk chain */
295
static void __init ps2esdi_geninit(void)
296
{
297
        /*
298
           The first part contains the initialization code
299
           for the ESDI disk subsystem.  All we really do
300
           is search for the POS registers of the controller
301
           to do some simple setup operations.  First, we
302
           must ensure that the controller is installed,
303
           enabled, and configured as PRIMARY.  Then we must
304
           determine the DMA arbitration level being used by
305
           the controller so we can handle data transfer
306
           operations properly.  If all of this works, then
307
           we will set the INIT_FLAG to a non-zero value.
308
         */
309
 
310
        int slot = 0, i, reset_start, reset_end;
311
        u_char status;
312
        unsigned short adapterID;
313
 
314
        if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) {
315
                adapterID = INTG_ESDI_ID;
316
                printk("%s: integrated ESDI adapter found in slot %d\n",
317
                       DEVICE_NAME, slot+1);
318
#ifndef MODULE
319
                mca_set_adapter_name(slot, "PS/2 Integrated ESDI");
320
#endif
321
        } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) {
322
                adapterID = NRML_ESDI_ID;
323
                printk("%s: normal ESDI adapter found in slot %d\n",
324
                       DEVICE_NAME, slot+1);
325
                mca_set_adapter_name(slot, "PS/2 ESDI");
326
        } else {
327
                return;
328
        }
329
 
330
        ps2esdi_slot = slot;
331
        mca_mark_as_used(slot);
332
        mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL);
333
 
334
        /* Found the slot - read the POS register 2 to get the necessary
335
           configuration and status information.  POS register 2 has the
336
           following information :
337
           Bit           Function
338
           7             reserved = 0
339
           6             arbitration method
340
 
341
           1 - fairness disabled, linear priority assignment
342
           5-2           arbitration level
343
           1             alternate address
344
           1              alternate address
345
 
346
 
347
         */
348
 
349
        status = mca_read_stored_pos(slot, 2);
350
        /* is it enabled ? */
351
        if (!(status & STATUS_ENABLED)) {
352
                printk("%s: ESDI adapter disabled\n", DEVICE_NAME);
353
                return;
354
        }
355
        /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can
356
           share with the SCSI driver */
357
        if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
358
                  SA_INTERRUPT | SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
359
            && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
360
                           SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
361
            ) {
362
                printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ);
363
                return;
364
        }
365
        if (status & STATUS_ALTERNATE)
366
                io_base = ALT_IO_BASE;
367
        else
368
                io_base = PRIMARY_IO_BASE;
369
 
370
        /* get the dma arbitration level */
371
        dma_arb_level = (status >> 2) & 0xf;
372
 
373
        /* BA */
374
        printk("%s: DMA arbitration level : %d\n",
375
               DEVICE_NAME, dma_arb_level);
376
 
377
        LITE_ON;
378
        current_int_handler = ps2esdi_initial_reset_int_handler;
379
        reset_ctrl();
380
        reset_status = 0;
381
        reset_start = jiffies;
382
        while (!reset_status) {
383
                init_timer(&esdi_timer);
384
                esdi_timer.expires = jiffies + HZ;
385
                esdi_timer.data = 0;
386
                add_timer(&esdi_timer);
387
                sleep_on(&ps2esdi_int);
388
        }
389
        reset_end = jiffies;
390
        LITE_OFF;
391
        printk("%s: reset interrupt after %d jiffies,  %u.%02u secs\n",
392
               DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ,
393
               (reset_end - reset_start) % HZ);
394
 
395
 
396
        /* Integrated ESDI Disk and Controller has only one drive! */
397
        if (adapterID == INTG_ESDI_ID) {/* if not "normal" PS2 ESDI adapter */
398
                ps2esdi_drives = 1;     /* then we have only one physical disk! */              intg_esdi = 1;
399
        }
400
 
401
 
402
 
403
        /* finally this part sets up some global data structures etc. */
404
 
405
        ps2esdi_get_device_cfg();
406
 
407
        /* some annoyance in the above routine returns TWO drives?
408
         Is something else happining in the background?
409
         Regaurdless we fix the # of drives again. AJK */
410
        /* Integrated ESDI Disk and Controller has only one drive! */
411
        if (adapterID == INTG_ESDI_ID)  /* if not "normal" PS2 ESDI adapter */
412
                ps2esdi_drives = 1;     /* Not three or two, ONE DAMNIT! */
413
 
414
        current_int_handler = ps2esdi_normal_interrupt_handler;
415
 
416
        ps2esdi_gendisk.nr_real = ps2esdi_drives;
417
 
418
        /* 128 was old default, maybe maxsect=255 is ok too? - Paul G. */
419
        for (i = 0; i < (MAX_HD << 6); i++) {
420
                ps2esdi_maxsect[i] = 128;
421
                ps2esdi_blocksizes[i] = 1024;
422
        }
423
 
424
        request_dma(dma_arb_level, "ed");
425
        request_region(io_base, 4, "ed");
426
        blksize_size[MAJOR_NR] = ps2esdi_blocksizes;
427
        max_sectors[MAJOR_NR] = ps2esdi_maxsect;
428
 
429
        for (i = 0; i < ps2esdi_drives; i++) {
430
                register_disk(&ps2esdi_gendisk,MKDEV(MAJOR_NR,i<<6),1<<6,
431
                                &ps2esdi_fops,
432
                                ps2esdi_info[i].head * ps2esdi_info[i].sect *
433
                                ps2esdi_info[i].cyl);
434
                ps2esdi_valid[i] = 1;
435
        }
436
}
437
 
438
static void __init ps2esdi_get_device_cfg(void)
439
{
440
        u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH];
441
 
442
        /*BA */ printk("%s: Drive 0\n", DEVICE_NAME);
443
        current_int_handler = ps2esdi_geometry_int_handler;
444
        cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600;
445
        cmd_blk[1] = 0;
446
        no_int_yet = TRUE;
447
        ps2esdi_out_cmd_blk(cmd_blk);
448
        if (no_int_yet)
449
                sleep_on(&ps2esdi_int);
450
 
451
        if (ps2esdi_drives > 1) {
452
                printk("%s: Drive 1\n", DEVICE_NAME);   /*BA */
453
                cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600;
454
                cmd_blk[1] = 0;
455
                no_int_yet = TRUE;
456
                ps2esdi_out_cmd_blk(cmd_blk);
457
                if (no_int_yet)
458
                        sleep_on(&ps2esdi_int);
459
        }                       /* if second physical drive is present */
460
        return;
461
}
462
 
463
/* strategy routine that handles most of the IO requests */
464
static void do_ps2esdi_request(request_queue_t * q)
465
{
466
        u_int block, count;
467
        /* since, this routine is called with interrupts cleared - they
468
           must be before it finishes  */
469
 
470
#if 0
471
        printk("%s:got request. device : %d minor : %d command : %d  sector : %ld count : %ld, buffer: %p\n",
472
               DEVICE_NAME,
473
               CURRENT_DEV, MINOR(CURRENT->rq_dev),
474
               CURRENT->cmd, CURRENT->sector,
475
               CURRENT->current_nr_sectors, CURRENT->buffer);
476
#endif
477
 
478
        /* standard macro that ensures that requests are really on the
479
           list + sanity checks.                     */
480
        INIT_REQUEST;
481
 
482
        if (virt_to_bus(CURRENT->buffer + CURRENT->current_nr_sectors * 512) > 16 * MB) {
483
                printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
484
                end_request(FAIL);
485
        }                       /* check for above 16Mb dmas */
486
        else if ((CURRENT_DEV < ps2esdi_drives) &&
487
            (CURRENT->sector + CURRENT->current_nr_sectors <=
488
             ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects)) {
489
#if 0
490
                printk("%s:got request. device : %d minor : %d command : %d  sector : %ld count : %ld\n",
491
                       DEVICE_NAME,
492
                       CURRENT_DEV, MINOR(CURRENT->rq_dev),
493
                       CURRENT->cmd, CURRENT->sector,
494
                       CURRENT->current_nr_sectors);
495
#endif
496
 
497
 
498
                block = CURRENT->sector + ps2esdi[MINOR(CURRENT->rq_dev)].start_sect;
499
 
500
#if 0
501
                printk("%s: blocknumber : %d\n", DEVICE_NAME, block);
502
#endif
503
                count = CURRENT->current_nr_sectors;
504
                switch (CURRENT->cmd) {
505
                case READ:
506
                        ps2esdi_readwrite(READ, CURRENT_DEV, block, count);
507
                        break;
508
                case WRITE:
509
                        ps2esdi_readwrite(WRITE, CURRENT_DEV, block, count);
510
                        break;
511
                default:
512
                        printk("%s: Unknown command\n", DEVICE_NAME);
513
                        end_request(FAIL);
514
                        break;
515
                }               /* handle different commands */
516
        }
517
        /* is request is valid */
518
        else {
519
                printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives,
520
                       CURRENT->sector, ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects);
521
                end_request(FAIL);
522
        }
523
 
524
}                               /* main strategy routine */
525
 
526
/* resets the ESDI adapter */
527
static void reset_ctrl(void)
528
{
529
 
530
        u_long expire;
531
        u_short status;
532
 
533
        /* enable interrupts on the controller */
534
        status = inb(ESDI_INTRPT);
535
        outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);     /* to be sure we don't have
536
                                                           any interrupt pending... */
537
        outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL);
538
 
539
        /* read the ESDI status port - if the controller is not busy,
540
           simply do a soft reset (fast) - otherwise we'll have to do a
541
           hard (slow) reset.  */
542
        if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) {
543
                /*BA */ printk("%s: soft reset...\n", DEVICE_NAME);
544
                outb_p(CTRL_SOFT_RESET, ESDI_ATTN);
545
        }
546
        /* soft reset */
547
        else {
548
                /*BA */
549
                printk("%s: hard reset...\n", DEVICE_NAME);
550
                outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
551
                expire = jiffies + 2*HZ;
552
                while (time_before(jiffies, expire));
553
                outb_p(1, ESDI_CONTROL);
554
        }                       /* hard reset */
555
 
556
 
557
}                               /* reset the controller */
558
 
559
/* called by the strategy routine to handle read and write requests */
560
static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count)
561
{
562
 
563
        u_short track, head, cylinder, sector;
564
        u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
565
        int err;
566
 
567
        /* do some relevant arithmatic */
568
        track = block / ps2esdi_info[drive].sect;
569
        head = track % ps2esdi_info[drive].head;
570
        cylinder = track / ps2esdi_info[drive].head;
571
        sector = block % ps2esdi_info[drive].sect;
572
 
573
#if 0
574
        printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector);
575
#endif
576
        /* call the routine that actually fills out a command block */
577
        ps2esdi_fill_cmd_block
578
            (cmd_blk,
579
             (cmd == READ) ? CMD_READ : CMD_WRITE,
580
             cylinder, head, sector,
581
             CURRENT->current_nr_sectors, drive);
582
 
583
        spin_unlock_irq(&io_request_lock);
584
        /* send the command block to the controller */
585
        err = ps2esdi_out_cmd_blk(cmd_blk);
586
        spin_lock_irq(&io_request_lock);
587
 
588
        if (err) {
589
                printk(KERN_ERR "%s: Controller failed\n", DEVICE_NAME);
590
                if ((++CURRENT->errors) >= MAX_RETRIES)
591
                        end_request(FAIL);
592
        }
593
        /* check for failure to put out the command block */
594
        else {
595
#if 0
596
                printk("%s: waiting for xfer\n", DEVICE_NAME);
597
#endif
598
                /* turn disk lights on */
599
                LITE_ON;
600
        }
601
 
602
}                               /* ps2esdi_readwrite */
603
 
604
/* fill out the command block */
605
static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
606
 u_short cyl, u_short head, u_short sector, u_short length, u_char drive)
607
{
608
 
609
        cmd_blk[0] = (drive << 5) | cmd;
610
        cmd_blk[1] = length;
611
        cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
612
        cmd_blk[3] = (cyl & 0x3E0) >> 5;
613
 
614
}                               /* fill out the command block */
615
 
616
/* write a command block to the controller */
617
static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
618
{
619
 
620
        int i, j;
621
        u_char status;
622
 
623
        /* enable interrupts */
624
        outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
625
 
626
        /* do not write to the controller, if it is busy */
627
        for (i = jiffies + ESDI_STAT_TIMEOUT; time_after(i, jiffies) && (inb(ESDI_STATUS) &
628
                                                          STATUS_BUSY););
629
 
630
#if 0
631
        printk("%s: i(1)=%d\n", DEVICE_NAME, i);
632
#endif
633
 
634
        /* if device is still busy - then just time out */
635
        if (inb(ESDI_STATUS) & STATUS_BUSY) {
636
                printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME);
637
                return ERROR;
638
        }                       /* timeout ??? */
639
        /* Set up the attention register in the controller */
640
        outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN);
641
 
642
#if 0
643
        printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1);
644
#endif
645
 
646
        /* one by one send each word out */
647
        for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
648
                status = inb(ESDI_STATUS);
649
                for (j = jiffies + ESDI_STAT_TIMEOUT;
650
                     time_after(j, jiffies) && (status & STATUS_BUSY) &&
651
                   (status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
652
                if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
653
#if 0
654
                        printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk);
655
#endif
656
                        outw(*cmd_blk++, ESDI_CMD_INT);
657
                } else {
658
                        printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
659
                               DEVICE_NAME, status);
660
                        return ERROR;
661
                }
662
        }                       /* send all words out */
663
        return OK;
664
}                               /* send out the commands */
665
 
666
 
667
/* prepare for dma - do all the necessary setup */
668
static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
669
{
670
        unsigned long flags;
671
#if 0
672
        printk("ps2esdi: b_wait: %p\n", &CURRENT->bh->b_wait);
673
#endif
674
        flags = claim_dma_lock();
675
 
676
        mca_disable_dma(dma_arb_level);
677
 
678
        mca_set_dma_addr(dma_arb_level, virt_to_bus(buffer));
679
 
680
        mca_set_dma_count(dma_arb_level, length * 512 / 2);
681
 
682
        mca_set_dma_mode(dma_arb_level, dma_xmode);
683
 
684
        mca_enable_dma(dma_arb_level);
685
 
686
        release_dma_lock(flags);
687
 
688
}                               /* prepare for dma */
689
 
690
 
691
 
692
static void ps2esdi_interrupt_handler(int irq, void *dev_id,
693
                                      struct pt_regs *regs)
694
{
695
        u_int int_ret_code;
696
 
697
        if (inb(ESDI_STATUS) & STATUS_INTR) {
698
                int_ret_code = inb(ESDI_INTRPT);
699
                if (current_int_handler) {
700
                        /* Disable adapter interrupts till processing is finished */
701
                        outb(CTRL_DISABLE_INTR, ESDI_CONTROL);
702
                        current_int_handler(int_ret_code);
703
                } else
704
                        printk("%s: help ! No interrupt handler.\n", DEVICE_NAME);
705
        } else {
706
                return;
707
        }
708
}
709
 
710
static void ps2esdi_initial_reset_int_handler(u_int int_ret_code)
711
{
712
 
713
        switch (int_ret_code & 0xf) {
714
        case INT_RESET:
715
                /*BA */
716
                printk("%s: initial reset completed.\n", DEVICE_NAME);
717
                outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
718
                wake_up(&ps2esdi_int);
719
                break;
720
        case INT_ATTN_ERROR:
721
                printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
722
                       int_ret_code);
723
                printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS));
724
                break;
725
        default:
726
                printk("%s: initial reset handler received interrupt: %02X\n",
727
                       DEVICE_NAME, int_ret_code);
728
                outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
729
                break;
730
        }
731
        outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
732
}
733
 
734
 
735
static void ps2esdi_geometry_int_handler(u_int int_ret_code)
736
{
737
        u_int status, drive_num;
738
        unsigned long rba;
739
        int i;
740
 
741
        drive_num = int_ret_code >> 5;
742
        switch (int_ret_code & 0xf) {
743
        case INT_CMD_COMPLETE:
744
                for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
745
                if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
746
                        printk("%s: timeout reading status word\n", DEVICE_NAME);
747
                        outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
748
                        break;
749
                }
750
                status = inw(ESDI_STT_INT);
751
                if ((status & 0x1F) == CMD_GET_DEV_CONFIG) {
752
#define REPLY_WORDS 5           /* we already read word 0 */
753
                        u_short reply[REPLY_WORDS];
754
 
755
                        if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) {
756
                                /*BA */
757
                                printk("%s: Device Configuration Status for drive %u\n",
758
                                       DEVICE_NAME, drive_num);
759
 
760
                                printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8);
761
 
762
                                printk
763
                                    ("Config bits: %s%s%s%s%s\n",
764
                                     (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "",
765
                                     ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS))
766
                                 ? "Zero Defect, " : "Defects Present, ",
767
                                     (reply[0] & CONFIG_SF) ? "Skewed Format, " : "",
768
                                     (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ",
769
                                     (reply[0] & CONFIG_RT) ? "No Retries" : "Retries");
770
 
771
                                rba = reply[1] | ((unsigned long) reply[2] << 16);
772
                                printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba);
773
 
774
                                printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
775
                                       DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff);
776
 
777
                                if (!ps2esdi_info[drive_num].head) {
778
                                        ps2esdi_info[drive_num].head = 64;
779
                                        ps2esdi_info[drive_num].sect = 32;
780
                                        ps2esdi_info[drive_num].cyl = rba / (64 * 32);
781
                                        ps2esdi_info[drive_num].wpcom = 0;
782
                                        ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl;
783
                                        ps2esdi_info[drive_num].ctl = 8;
784
                                        if (tp720esdi) {        /* store the retrieved parameters */
785
                                                ps2esdi_info[0].head = reply[4] & 0Xff;
786
                                                ps2esdi_info[0].sect = reply[4] >> 8;
787
                                                ps2esdi_info[0].cyl = reply[3];
788
                                                ps2esdi_info[0].wpcom = 0;
789
                                                ps2esdi_info[0].lzone = reply[3];
790
                                        } else {
791
                                                if (!intg_esdi)
792
                                                        ps2esdi_drives++;
793
                                        }
794
                                }
795
#ifdef OBSOLETE
796
                                if (!ps2esdi_info[drive_num].head) {
797
                                        ps2esdi_info[drive_num].head = reply[4] & 0Xff;
798
                                        ps2esdi_info[drive_num].sect = reply[4] >> 8;
799
                                        ps2esdi_info[drive_num].cyl = reply[3];
800
                                        ps2esdi_info[drive_num].wpcom = 0;
801
                                        ps2esdi_info[drive_num].lzone = reply[3];
802
                                        if (tp720esdi) {        /* store the retrieved parameters */
803
                                                ps2esdi_info[0].head = reply[4] & 0Xff;
804
                                                ps2esdi_info[0].sect = reply[4] >> 8;
805
                                                ps2esdi_info[0].cyl = reply[3];
806
                                                ps2esdi_info[0].wpcom = 0;
807
                                                ps2esdi_info[0].lzone = reply[3];
808
                                        } else {
809
                                                ps2esdi_drives++;
810
                                        }
811
                                }
812
#endif
813
 
814
                        } else
815
                                printk("%s: failed while getting device config\n", DEVICE_NAME);
816
#undef REPLY_WORDS
817
                } else
818
                        printk("%s: command %02X unknown by geometry handler\n",
819
                               DEVICE_NAME, status & 0x1f);
820
 
821
                outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
822
                break;
823
 
824
        case INT_ATTN_ERROR:
825
                printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
826
                       int_ret_code);
827
                printk("%s: Device not available\n", DEVICE_NAME);
828
                break;
829
        case INT_CMD_ECC:
830
        case INT_CMD_RETRY:
831
        case INT_CMD_ECC_RETRY:
832
        case INT_CMD_WARNING:
833
        case INT_CMD_ABORT:
834
        case INT_CMD_FAILED:
835
        case INT_DMA_ERR:
836
        case INT_CMD_BLK_ERR:
837
                /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME);
838
                dump_cmd_complete_status(int_ret_code);
839
                outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
840
                break;
841
        default:
842
                printk("%s: Unknown interrupt reason: %02X\n",
843
                       DEVICE_NAME, int_ret_code & 0xf);
844
                outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
845
                break;
846
        }
847
 
848
        wake_up(&ps2esdi_int);
849
        no_int_yet = FALSE;
850
        outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
851
 
852
}
853
 
854
static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
855
{
856
        unsigned long flags;
857
        u_int status;
858
        u_int ending;
859
        int i;
860
 
861
        switch (int_ret_code & 0x0f) {
862
        case INT_TRANSFER_REQ:
863
                ps2esdi_prep_dma(CURRENT->buffer, CURRENT->current_nr_sectors,
864
                    (CURRENT->cmd == READ)
865
                    ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER
866
                    : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ);
867
                outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
868
                ending = -1;
869
                break;
870
 
871
        case INT_ATTN_ERROR:
872
                printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
873
                       int_ret_code);
874
                outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
875
                ending = FAIL;
876
                break;
877
 
878
        case INT_CMD_COMPLETE:
879
                for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
880
                if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
881
                        printk("%s: timeout reading status word\n", DEVICE_NAME);
882
                        outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
883
                        outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
884
                        if ((++CURRENT->errors) >= MAX_RETRIES)
885
                                ending = FAIL;
886
                        else
887
                                ending = -1;
888
                        break;
889
                }
890
                status = inw(ESDI_STT_INT);
891
                switch (status & 0x1F) {
892
                case (CMD_READ & 0xff):
893
                case (CMD_WRITE & 0xff):
894
                        LITE_OFF;
895
                        outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
896
                        outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
897
#if 0
898
                        printk("ps2esdi: cmd_complete b_wait: %p\n", &CURRENT->bh->b_wait);
899
#endif
900
                        ending = SUCCES;
901
                        break;
902
                default:
903
                        printk("%s: interrupt for unknown command %02X\n",
904
                               DEVICE_NAME, status & 0x1f);
905
                        outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
906
                        outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
907
                        ending = -1;
908
                        break;
909
                }
910
                break;
911
        case INT_CMD_ECC:
912
        case INT_CMD_RETRY:
913
        case INT_CMD_ECC_RETRY:
914
                LITE_OFF;
915
                dump_cmd_complete_status(int_ret_code);
916
                outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
917
                outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
918
                ending = SUCCES;
919
                break;
920
        case INT_CMD_WARNING:
921
        case INT_CMD_ABORT:
922
        case INT_CMD_FAILED:
923
        case INT_DMA_ERR:
924
                LITE_OFF;
925
                dump_cmd_complete_status(int_ret_code);
926
                outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
927
                outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
928
                if ((++CURRENT->errors) >= MAX_RETRIES)
929
                        ending = FAIL;
930
                else
931
                        ending = -1;
932
                break;
933
 
934
        case INT_CMD_BLK_ERR:
935
                dump_cmd_complete_status(int_ret_code);
936
                outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
937
                outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
938
                ending = FAIL;
939
                break;
940
 
941
        case INT_CMD_FORMAT:
942
                printk("%s: huh ? Who issued this format command ?\n"
943
                       ,DEVICE_NAME);
944
                outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
945
                outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
946
                ending = -1;
947
                break;
948
 
949
        case INT_RESET:
950
                /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
951
                outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
952
                outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
953
                ending = -1;
954
                break;
955
 
956
        default:
957
                printk("%s: Unknown interrupt reason: %02X\n",
958
                       DEVICE_NAME, int_ret_code & 0xf);
959
                outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
960
                outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
961
                ending = -1;
962
                break;
963
        }
964
        if(ending != -1) {
965
                spin_lock_irqsave(&io_request_lock, flags);
966
                end_request(ending);
967
                do_ps2esdi_request(BLK_DEFAULT_QUEUE(MAJOR_NR));
968
                spin_unlock_irqrestore(&io_request_lock, flags);
969
        }
970
}                               /* handle interrupts */
971
 
972
 
973
 
974
static int ps2esdi_read_status_words(int num_words,
975
                                     int max_words,
976
                                     u_short * buffer)
977
{
978
        int i;
979
 
980
        for (; max_words && num_words; max_words--, num_words--, buffer++) {
981
                for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
982
                if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
983
                        printk("%s: timeout reading status word\n", DEVICE_NAME);
984
                        return FAIL;
985
                }
986
                *buffer = inw(ESDI_STT_INT);
987
        }
988
        return SUCCES;
989
}
990
 
991
 
992
 
993
 
994
static void dump_cmd_complete_status(u_int int_ret_code)
995
{
996
#define WAIT_FOR_STATUS \
997
  for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
998
    if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
999
    printk("%s: timeout reading status word\n",DEVICE_NAME); \
1000
    return; \
1001
    }
1002
 
1003
        int i, word_count;
1004
        u_short stat_word;
1005
        u_long rba;
1006
 
1007
        printk("%s: Device: %u, interrupt ID: %02X\n",
1008
               DEVICE_NAME, int_ret_code >> 5,
1009
               int_ret_code & 0xf);
1010
 
1011
        WAIT_FOR_STATUS;
1012
        stat_word = inw(ESDI_STT_INT);
1013
        word_count = (stat_word >> 8) - 1;
1014
        printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count,
1015
               stat_word & 0xff);
1016
 
1017
        if (word_count--) {
1018
                WAIT_FOR_STATUS;
1019
                stat_word = inw(ESDI_STT_INT);
1020
                printk("%s: command status code: %02X, command error code: %02X\n",
1021
                       DEVICE_NAME, stat_word >> 8, stat_word & 0xff);
1022
        }
1023
        if (word_count--) {
1024
                WAIT_FOR_STATUS;
1025
                stat_word = inw(ESDI_STT_INT);
1026
                printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME,
1027
                       (stat_word & 0x1000) ? "Ready, " : "Not Ready, ",
1028
                  (stat_word & 0x0800) ? "Selected, " : "Not Selected, ",
1029
                       (stat_word & 0x0400) ? "Write Fault, " : "",
1030
                       (stat_word & 0x0200) ? "Track 0, " : "",
1031
                (stat_word & 0x0100) ? "Seek or command complete, " : "",
1032
                       stat_word >> 8);
1033
        }
1034
        if (word_count--) {
1035
                WAIT_FOR_STATUS;
1036
                stat_word = inw(ESDI_STT_INT);
1037
                printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word);
1038
        }
1039
        if (word_count -= 2) {
1040
                WAIT_FOR_STATUS;
1041
                rba = inw(ESDI_STT_INT);
1042
                WAIT_FOR_STATUS;
1043
                rba |= inw(ESDI_STT_INT) << 16;
1044
                printk(", Last Cyl: %u Head: %u Sector: %u\n",
1045
                       (u_short) ((rba & 0x1ff80000) >> 11),
1046
                 (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f));
1047
        } else
1048
                printk("\n");
1049
 
1050
        if (word_count--) {
1051
                WAIT_FOR_STATUS;
1052
                stat_word = inw(ESDI_STT_INT);
1053
                printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word);
1054
        }
1055
        printk("\n");
1056
 
1057
#undef WAIT_FOR_STATUS
1058
 
1059
}
1060
 
1061
 
1062
static int ps2esdi_open(struct inode *inode, struct file *file)
1063
{
1064
        int dev = DEVICE_NR(inode->i_rdev);
1065
 
1066
        if (dev < ps2esdi_drives) {
1067
                while (!ps2esdi_valid[dev])
1068
                        sleep_on(&ps2esdi_wait_open);
1069
 
1070
                access_count[dev]++;
1071
 
1072
                return (0);
1073
        } else
1074
                return (-ENODEV);
1075
}
1076
 
1077
 
1078
 
1079
static int ps2esdi_release(struct inode *inode, struct file *file)
1080
{
1081
        int dev = DEVICE_NR(inode->i_rdev);
1082
 
1083
        if (dev < ps2esdi_drives) {
1084
                access_count[dev]--;
1085
        }
1086
        return 0;
1087
}
1088
 
1089
 
1090
 
1091
static int ps2esdi_ioctl(struct inode *inode,
1092
                         struct file *file, u_int cmd, u_long arg)
1093
{
1094
 
1095
        struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg;
1096
        int dev = DEVICE_NR(inode->i_rdev), err;
1097
 
1098
        if (inode && (dev < ps2esdi_drives))
1099
                switch (cmd) {
1100
                case HDIO_GETGEO:
1101
                        if (arg) {
1102
                                if ((err = verify_area(VERIFY_WRITE, geometry, sizeof(*geometry))))
1103
                                        return (err);
1104
                                put_user(ps2esdi_info[dev].head, (char *) &geometry->heads);
1105
                                put_user(ps2esdi_info[dev].sect, (char *) &geometry->sectors);
1106
                                put_user(ps2esdi_info[dev].cyl, (short *) &geometry->cylinders);
1107
                                put_user(ps2esdi[MINOR(inode->i_rdev)].start_sect,
1108
                                            (long *) &geometry->start);
1109
 
1110
                                return (0);
1111
                        }
1112
                        break;
1113
 
1114
                case BLKRRPART:
1115
                        if (!capable(CAP_SYS_ADMIN))
1116
                                return -EACCES;
1117
                        return (ps2esdi_reread_partitions(inode->i_rdev));
1118
 
1119
                case BLKGETSIZE:
1120
                case BLKGETSIZE64:
1121
                case BLKROSET:
1122
                case BLKROGET:
1123
                case BLKRASET:
1124
                case BLKRAGET:
1125
                case BLKFLSBUF:
1126
                case BLKBSZGET:
1127
                case BLKBSZSET:
1128
                case BLKPG:
1129
                        return blk_ioctl(inode->i_rdev, cmd, arg);
1130
                }
1131
        return (-EINVAL);
1132
}
1133
 
1134
 
1135
 
1136
static int ps2esdi_reread_partitions(kdev_t dev)
1137
{
1138
        int target = DEVICE_NR(dev);
1139
        int start = target << ps2esdi_gendisk.minor_shift;
1140
        int partition;
1141
 
1142
        ps2esdi_valid[target] = (access_count[target] != 1);
1143
        if (ps2esdi_valid[target])
1144
                return (-EBUSY);
1145
 
1146
        for (partition = ps2esdi_gendisk.max_p - 1;
1147
             partition >= 0; partition--) {
1148
                int minor = (start | partition);
1149
                invalidate_device(MKDEV(MAJOR_NR, minor), 1);
1150
                ps2esdi_gendisk.part[minor].start_sect = 0;
1151
                ps2esdi_gendisk.part[minor].nr_sects = 0;
1152
        }
1153
 
1154
        grok_partitions(&ps2esdi_gendisk, target, 1<<6,
1155
                ps2esdi_info[target].head * ps2esdi_info[target].cyl * ps2esdi_info[target].sect);
1156
 
1157
        ps2esdi_valid[target] = 1;
1158
        wake_up(&ps2esdi_wait_open);
1159
 
1160
        return (0);
1161
}
1162
 
1163
static void ps2esdi_reset_timer(unsigned long unused)
1164
{
1165
 
1166
        int status;
1167
 
1168
        status = inb(ESDI_INTRPT);
1169
        if ((status & 0xf) == INT_RESET) {
1170
                outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);
1171
                outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
1172
                reset_status = 1;
1173
        }
1174
        wake_up(&ps2esdi_int);
1175
}
1176
 
1177
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.