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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [peripheral/] [atadevice.c] - Blame information for rev 19

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

Line No. Rev Author Line
1 19 jeremybenn
/* atadevice.c -- ATA Device simulation. Simulates a harddisk, using a local
2
   streams.
3
 
4
   Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
5
   Copyright (C) 2008 Embecosm Limited
6
 
7
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8
 
9
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
10
 
11
   This program is free software; you can redistribute it and/or modify it
12
   under the terms of the GNU General Public License as published by the Free
13
   Software Foundation; either version 3 of the License, or (at your option)
14
   any later version.
15
 
16
   This program is distributed in the hope that it will be useful, but WITHOUT
17
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19
   more details.
20
 
21
   You should have received a copy of the GNU General Public License along
22
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
23
 
24
/* This program is commented throughout in a fashion suitable for processing
25
   with Doxygen. */
26
 
27
 
28
/* Autoconf and/or portability configuration */
29
#include "config.h"
30
#include "port.h"
31
 
32
/* System includes */
33
#include <byteswap.h>
34
 
35
/* Package includes */
36
#include "atadevice.h"
37
#include "atadevice-cmdi.h"
38
#include "atacmd.h"
39
#include "abstract.h"
40
 
41
 
42
/*
43
 mandatory commands:
44
 - execute device diagnostics       (done)
45
 - flush cache
46
 - identify device                  (done)
47
 - initialize device parameters     (done)
48
 - read dma
49
 - read multiple
50
 - read sector(s)                   (done)
51
 - read verify sector(s)
52
 - seek
53
 - set features
54
 - set multiple mode
55
 - write dma
56
 - write multiple
57
 - write sector(s)
58
 
59
 
60
 optional commands:
61
 - download microcode
62
 - nop
63
 - read buffer
64
 - write buffer
65
 
66
 
67
 prohibited commands:
68
 - device reset
69
*/
70
 
71
 
72
/* Use a file to simulate a hard-disk                                 */
73
static FILE *
74
open_file (uint32_t * size, const char *filename)
75
{
76
  FILE *fp;
77
  unsigned long n;
78
 
79
  // TODO:
80
 
81
  /* check if a file with name 'filename' already exists             */
82
  if (!(fp = fopen (filename, "rb+")))
83
    if (!(fp = fopen (filename, "wb+")))
84
      {
85
        fprintf (stderr, "Warning: ata_open_file, cannot open hd-file %s\n",
86
                 filename);
87
        return NULL;
88
      }
89
    else
90
      {
91
        /* TODO create a file 'size' large */
92
        /* create a file 'size' large                                  */
93
        for (n = 0; n < *size; n++)
94
          fputc (0, fp);
95
      }
96
  else                          /* file already exist                                         */
97
    fprintf (stderr, "file %s already exists. Using existing file.\n",
98
             filename);
99
 
100
  /* get the size of the file. This is also the size of the harddisk */
101
  fseek (fp, 0, SEEK_END);
102
  *size = ftell (fp);
103
 
104
  return fp;
105
}
106
 
107
 
108
/* Use a the local filesystem as a hard-disk                          */
109
static FILE *
110
open_local (void)
111
{
112
  // TODO:
113
  fprintf (stderr, "Warning: Device type LOCAL is not yet supported: "
114
           "Defaulting to device type NO_CONNECT.");
115
  return NULL;
116
}
117
 
118
static void
119
ata_device_init (struct ata_device * device, int dev)
120
{
121
  /* set DeviceID                                                     */
122
  device->internals.dev = dev;
123
 
124
  /* generate stream for hd_simulation                                */
125
  switch (device->conf.type)
126
    {
127
    case TYPE_NO_CONNECT:
128
      device->conf.stream = NULL;
129
      break;
130
 
131
    case TYPE_FILE:
132
      device->conf.stream = open_file (&device->conf.size, device->conf.file);
133
      break;
134
 
135
    case TYPE_LOCAL:
136
      device->conf.stream = open_local ();
137
      break;
138
 
139
    default:
140
      fprintf (stderr, "Warning: Illegal device-type %d: "
141
               "Defaulting to type NO_CONNECT.\n", device->conf.type);
142
      device->conf.stream = NULL;
143
      break;
144
    }
145
 
146
  device->conf.size_sect = device->conf.size / BYTES_PER_SECTOR;
147
}
148
 
149
/*
150
  D E V I C E S _ I N I T
151
*/
152
void
153
ata_devices_init (struct ata_devices * devices)
154
{
155
  ata_device_init (&devices->device[0], 0);
156
 
157
  if (devices->device[0].conf.type)
158
    ata_device_init (&devices->device[1], ATA_DHR_DEV);
159
  else
160
    ata_device_init (&devices->device[1], 0);
161
}
162
 
163
/*
164
  D E V I C E S _ H W _ R E S E T
165
*/
166
static void
167
ata_device_hw_reset (struct ata_device * device, int reset_signal,
168
                     int daspo, int pdiagi, int daspi)
169
{
170
  /* check ata-device state                                         */
171
  if (device->internals.state == ATA_STATE_HW_RST)
172
    {
173
      if (!reset_signal)
174
        {
175
          /* hardware reset finished                                    */
176
 
177
          /* set sectors_per_track & heads_per_cylinders                */
178
          device->internals.sectors_per_track = device->conf.sectors;
179
          device->internals.heads_per_cylinder = device->conf.heads;
180
 
181
          /* set device1 input signals                                  */
182
          device->sigs.pdiagi = pdiagi;
183
          device->sigs.daspi = daspi;
184
 
185
          ata_execute_device_diagnostics_cmd (device);
186
 
187
          /* clear busy bit                                             */
188
          device->regs.status &= ~ATA_SR_BSY;
189
 
190
          /* set DRDY bit, when not a PACKET device                     */
191
          if (!device->conf.packet)
192
            device->regs.status |= ATA_SR_DRDY;
193
 
194
          /* set new state                                              */
195
          device->internals.state = ATA_STATE_IDLE;
196
        }
197
    }
198
  else if (reset_signal)
199
    {
200
      /* hardware reset signal asserted, stop what we are doing     */
201
 
202
      /* negate bus signals                                         */
203
      device->sigs.iordy = 0;
204
      device->sigs.intrq = 0;
205
      device->sigs.dmarq = 0;
206
      device->sigs.pdiago = 0;
207
      device->sigs.daspo = daspo;
208
 
209
      /* set busy bit                                               */
210
      device->regs.status |= ATA_SR_BSY;
211
 
212
      /* set new state                                              */
213
      device->internals.state = ATA_STATE_HW_RST;
214
    }
215
}
216
 
217
/* power-on and hardware reset                                        */
218
void
219
ata_devices_hw_reset (struct ata_devices * devices, int reset_signal)
220
{
221
  /* find device 0                                                    */
222
  if ((devices->device[0].conf.stream) && (devices->device[1].conf.stream))
223
    {
224
      /* this one is simple, device0 is device0                         */
225
 
226
      /* 1) handle device1 first                                        */
227
      ata_device_hw_reset (&devices->device[1], reset_signal, 1,        /* assert dasp, this is device1          */
228
                           0,    /* negate pdiag input, no more devices   */
229
                           0);   /* negate dasp input, no more devices    */
230
 
231
      /* 2) Then handle device0                                         */
232
      ata_device_hw_reset (&devices->device[0], reset_signal,
233
                           0,
234
                           devices->device[1].sigs.pdiago,
235
                           devices->device[1].sigs.daspo);
236
    }
237
  else if (devices->device[0].conf.stream)
238
    {
239
      /* device0 is device0, there's no device1                         */
240
      ata_device_hw_reset (&devices->device[0], reset_signal, 0,  /* negate dasp, this is device0          */
241
                           0,    /* negate pdiag input, there's no device1 */
242
                           0);   /* negate dasp input, there's no device1 */
243
    }
244
  else if (devices->device[1].conf.stream)
245
    {
246
      /* device1 is (logical) device0, there's no (physical) device0    */
247
      ata_device_hw_reset (&devices->device[1], reset_signal, 0, /* negate dasp, this is device0          */
248
                           0,    /* negate pdiag input, there's no device1 */
249
                           0);   /* negate dasp input, there's no device1 */
250
    }
251
}
252
 
253
 
254
/*
255
  D E V I C E S _ D O _ C O N T R O L _ R E G I S T E R
256
 
257
  Handles - software reset
258
          - Interrupt enable bit
259
*/
260
static void
261
ata_device_do_control_register (struct ata_device * device)
262
{
263
  /* TODO respond to new values of nIEN */
264
  /* if device not selected, respond to new values of nIEN & SRST */
265
 
266
  /* check if SRST bit is set                                         */
267
  if (device->regs.device_control & ATA_DCR_RST)
268
    {
269
      if (device->internals.state == ATA_STATE_IDLE)
270
        {                       /* start software reset                                       */
271
          /* negate bus signals                                         */
272
          device->sigs.pdiago = 0;
273
          device->sigs.intrq = 0;
274
          device->sigs.iordy = 0;
275
          device->sigs.dmarq = 0;
276
 
277
          /* set busy bit                                               */
278
          device->regs.status |= ATA_SR_BSY;
279
 
280
          /* set new state                                              */
281
          device->internals.state = ATA_STATE_SW_RST;
282
        }
283
    }
284
  else if (device->internals.state == ATA_STATE_SW_RST)
285
    {                           /* are we doing a software reset ??                             */
286
      /* SRST bit cleared, end of software reset                      */
287
 
288
      /*execute device diagnostics                                    */
289
      ata_execute_device_diagnostics_cmd (device);
290
 
291
      /* clear busy bit                                               */
292
      device->regs.status &= ~ATA_SR_BSY;
293
 
294
      /* set DRDY bit, when not a PACKET device                       */
295
      if (!device->conf.packet)
296
        device->regs.status |= ATA_SR_DRDY;
297
 
298
      /* set new state                                                */
299
      device->internals.state = ATA_STATE_IDLE;
300
    }
301
  /*
302
     <else> We are doing a hardware reset (or similar)
303
     ignore command
304
   */
305
}
306
 
307
 
308
/*
309
  D E V I C E S _ D O _ C O M M A N D _ R E G I S T E R
310
*/
311
static void
312
ata_device_do_command_register (struct ata_device * device)
313
{
314
  /* check BSY & DRQ                                                  */
315
  if ((device->regs.status & ATA_SR_BSY)
316
      || (device->regs.status & ATA_SR_DRQ))
317
    {
318
      if (device->regs.command != DEVICE_RESET)
319
        {
320
          fprintf (stderr, "Warning: ata_device_write, writing a command "
321
                   "while BSY or DRQ asserted.\n");
322
        }
323
    }
324
 
325
  /* check if device selected                                         */
326
  if ((device->regs.device_head & ATA_DHR_DEV) == device->internals.dev)
327
    ata_device_execute_cmd (device);
328
  else
329
    {
330
      /* if not selected, only respond to EXECUTE DEVICE DIAGNOSTICS  */
331
      if (device->regs.command == EXECUTE_DEVICE_DIAGNOSTICS)
332
        ata_device_execute_cmd (device);
333
    }
334
}
335
 
336
 
337
/*
338
  D E V I C E S _ R E A D
339
*/
340
/* Read from devices                                                  */
341
short
342
ata_devices_read (struct ata_devices * devices, char adr)
343
{
344
  struct ata_device *device;
345
 
346
  /* check for no connected devices                                 */
347
  if ((!devices->device[0].conf.stream) && (!devices->device[1].conf.stream))
348
    {
349
      fprintf (stderr, "Warning: ata_devices_read, no ata devices "
350
               "connected.\n");
351
    }
352
  else
353
    {
354
      /* check if both device0 and device1 are connected              */
355
      if ((devices->device[0].conf.stream)
356
          && (devices->device[1].conf.stream))
357
        {
358
          /* get the current active device                            */
359
          if (devices->device[1].regs.device_head & ATA_DHR_DEV)
360
            device = &devices->device[1];
361
          else
362
            device = &devices->device[0];
363
        }
364
      else
365
        {
366
          /* only one device connected                                */
367
          if (devices->device[1].conf.stream)
368
            device = &devices->device[1];
369
          else
370
            device = &devices->device[0];
371
        }
372
 
373
      /* return data provided by selected device                      */
374
      switch (adr)
375
        {
376
        case ATA_ASR:
377
          if ((device->regs.device_head & ATA_DHR_DEV) ==
378
              device->internals.dev)
379
            return device->regs.status;
380
          else
381
            {
382
              return 0;          // return 0 when device0 responds for device1
383
            }
384
 
385
        case ATA_CHR:
386
          return device->regs.cylinder_high;
387
 
388
        case ATA_CLR:
389
          return device->regs.cylinder_low;
390
 
391
        case ATA_DR:
392
          if (!device->regs.status & ATA_SR_DRQ)
393
            {
394
              return 0;
395
            }
396
          else
397
            {
398
              uint16_t val = LE16 (*device->internals.dbuf_ptr++);
399
              if (!--device->internals.dbuf_cnt)
400
                {
401
                  device->regs.status &= ~ATA_SR_DRQ;
402
                  if (device->internals.end_t_func)
403
                    device->internals.end_t_func (device);
404
                }
405
              return val;
406
            }
407
 
408
        case ATA_DHR:
409
          return device->regs.device_head;
410
 
411
        case ATA_ERR:
412
          return device->regs.error;
413
 
414
        case ATA_SCR:
415
          return device->regs.sector_count;
416
 
417
        case ATA_SNR:
418
          return device->regs.sector_number;
419
 
420
        case ATA_SR:
421
          if ((device->regs.device_head & ATA_DHR_DEV) ==
422
              device->internals.dev)
423
            {
424
              device->sigs.intrq = 0;
425
              return device->regs.status;
426
            }
427
 
428
          return 0;              // return 0 when device0 responds for device1
429
 
430
//        case ATA_DA   :
431
//          return device -> regs.status;
432
        }
433
    }
434
  return 0;
435
}
436
 
437
 
438
/*
439
  D E V I C E S _ W R I T E
440
*/
441
/* write to a single device                                           */
442
static void
443
ata_device_write (struct ata_device * device, char adr, short value)
444
{
445
  switch (adr)
446
    {
447
    case ATA_CR:
448
      device->regs.command = value;
449
 
450
      /* check command register settings and execute command    */
451
      ata_device_do_command_register (device);
452
      break;
453
 
454
 
455
    case ATA_CHR:
456
      device->regs.cylinder_high = value;
457
      break;
458
 
459
    case ATA_CLR:
460
      device->regs.cylinder_low = value;
461
      break;
462
 
463
    case ATA_DR:
464
      if (!device->regs.status & ATA_SR_DRQ)
465
        {
466
          break;
467
        }
468
      else
469
        {
470
          *device->internals.dbuf_ptr++ = LE16 (value);
471
          if (!--device->internals.dbuf_cnt)
472
            {
473
              device->regs.status &= ~ATA_SR_DRQ;
474
              if (device->internals.end_t_func)
475
                device->internals.end_t_func (device);
476
            }
477
        }
478
      device->regs.dataport_i = value;
479
      break;
480
 
481
    case ATA_DCR:
482
      device->regs.device_control = value;
483
      ata_device_do_control_register (device);
484
      break;
485
 
486
    case ATA_DHR:
487
      device->regs.device_head = value;
488
      break;
489
 
490
    case ATA_FR:
491
      device->regs.features = value;
492
      break;
493
 
494
    case ATA_SCR:
495
      device->regs.sector_count = value;
496
      break;
497
 
498
    case ATA_SNR:
499
      device->regs.sector_number = value;
500
      break;
501
 
502
    }                           //endcase
503
}
504
 
505
/* Write to devices                                                   */
506
void
507
ata_devices_write (struct ata_devices * devices, char adr, short value)
508
{
509
  /* check for no connected devices                                 */
510
  if (!devices->device[0].conf.stream && !devices->device[1].conf.stream)
511
    {
512
      fprintf (stderr, "Warning: ata_devices_write, no ata devices "
513
               "connected.\n");
514
    }
515
  else
516
    {
517
      /* first device                                                 */
518
      if (devices->device[0].conf.stream)
519
        ata_device_write (&devices->device[0], adr, value);
520
 
521
      /* second device                                                */
522
      if (devices->device[1].conf.stream)
523
        ata_device_write (&devices->device[1], adr, value);
524
    }
525
}

powered by: WebSVN 2.1.0

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