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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [peripheral/] [atadevice.c] - Blame information for rev 1751

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

Line No. Rev Author Line
1 1748 jeremybenn
/* atadevice.c -- ATA Device simulation. Simulates a harddisk, using a local
2
   streams.
3 876 rherveille
 
4 1748 jeremybenn
   Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
5
   Copyright (C) 2008 Embecosm Limited
6 876 rherveille
 
7 1748 jeremybenn
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8 876 rherveille
 
9 1748 jeremybenn
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
10 876 rherveille
 
11 1748 jeremybenn
   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 876 rherveille
 
16 1748 jeremybenn
   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 1350 nogj
 
21 1748 jeremybenn
   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 1350 nogj
 
24 1748 jeremybenn
/* This program is commented throughout in a fashion suitable for processing
25
   with Doxygen. */
26 1350 nogj
 
27 1748 jeremybenn
 
28
/* Autoconf and/or portability configuration */
29
#include "config.h"
30 1350 nogj
#include "port.h"
31 876 rherveille
 
32 1748 jeremybenn
/* System includes */
33
#include <byteswap.h>
34
 
35
/* Package includes */
36 876 rherveille
#include "atadevice.h"
37 1748 jeremybenn
#include "atadevice-cmdi.h"
38 876 rherveille
#include "atacmd.h"
39 1748 jeremybenn
#include "abstract.h"
40 1488 nogj
 
41
 
42 876 rherveille
/*
43
 mandatory commands:
44 919 rherveille
 - execute device diagnostics       (done)
45 876 rherveille
 - flush cache
46 919 rherveille
 - identify device                  (done)
47
 - initialize device parameters     (done)
48 876 rherveille
 - read dma
49
 - read multiple
50 919 rherveille
 - read sector(s)                   (done)
51 876 rherveille
 - 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 1693 nogj
/* Use a file to simulate a hard-disk                                 */
73 1748 jeremybenn
static FILE *
74
open_file (uint32_t * size, const char *filename)
75 876 rherveille
{
76 1748 jeremybenn
  FILE *fp;
77
  unsigned long n;
78 876 rherveille
 
79 1748 jeremybenn
  // TODO:
80 1693 nogj
 
81 1748 jeremybenn
  /* check if a file with name 'filename' already exists             */
82
  if (!(fp = fopen (filename, "rb+")))
83
    if (!(fp = fopen (filename, "wb+")))
84
      {
85 1751 jeremybenn
        fprintf (stderr, "Warning: ata_open_file, cannot open hd-file %s\n",
86
                 filename);
87 1748 jeremybenn
        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 1693 nogj
 
100 1748 jeremybenn
  /* 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 1693 nogj
 
104 1748 jeremybenn
  return fp;
105 876 rherveille
}
106
 
107
 
108 1693 nogj
/* Use a the local filesystem as a hard-disk                          */
109 1748 jeremybenn
static FILE *
110
open_local (void)
111 876 rherveille
{
112 1693 nogj
  // TODO:
113 1751 jeremybenn
  fprintf (stderr, "Warning: Device type LOCAL is not yet supported: "
114
           "Defaulting to device type NO_CONNECT.");
115 1693 nogj
  return NULL;
116
}
117
 
118 1748 jeremybenn
static void
119
ata_device_init (struct ata_device * device, int dev)
120 1693 nogj
{
121 876 rherveille
  /* set DeviceID                                                     */
122 1065 rherveille
  device->internals.dev = dev;
123 876 rherveille
 
124
  /* generate stream for hd_simulation                                */
125 1748 jeremybenn
  switch (device->conf.type)
126
    {
127 876 rherveille
    case TYPE_NO_CONNECT:
128 1695 nogj
      device->conf.stream = NULL;
129 876 rherveille
      break;
130
 
131
    case TYPE_FILE:
132 1748 jeremybenn
      device->conf.stream = open_file (&device->conf.size, device->conf.file);
133 876 rherveille
      break;
134
 
135
    case TYPE_LOCAL:
136 1748 jeremybenn
      device->conf.stream = open_local ();
137 876 rherveille
      break;
138
 
139
    default:
140 1751 jeremybenn
      fprintf (stderr, "Warning: Illegal device-type %d: "
141
               "Defaulting to type NO_CONNECT.\n", device->conf.type);
142 1695 nogj
      device->conf.stream = NULL;
143 876 rherveille
      break;
144 1748 jeremybenn
    }
145 1708 nogj
 
146
  device->conf.size_sect = device->conf.size / BYTES_PER_SECTOR;
147 876 rherveille
}
148
 
149 1693 nogj
/*
150
  D E V I C E S _ I N I T
151
*/
152 1748 jeremybenn
void
153
ata_devices_init (struct ata_devices * devices)
154 876 rherveille
{
155 1748 jeremybenn
  ata_device_init (&devices->device[0], 0);
156 876 rherveille
 
157 1748 jeremybenn
  if (devices->device[0].conf.type)
158
    ata_device_init (&devices->device[1], ATA_DHR_DEV);
159 1693 nogj
  else
160 1748 jeremybenn
    ata_device_init (&devices->device[1], 0);
161 1693 nogj
}
162 876 rherveille
 
163 1693 nogj
/*
164
  D E V I C E S _ H W _ R E S E T
165
*/
166 1748 jeremybenn
static void
167
ata_device_hw_reset (struct ata_device * device, int reset_signal,
168
                     int daspo, int pdiagi, int daspi)
169 1693 nogj
{
170
  /* check ata-device state                                         */
171 1748 jeremybenn
  if (device->internals.state == ATA_STATE_HW_RST)
172
    {
173
      if (!reset_signal)
174
        {
175
          /* hardware reset finished                                    */
176 876 rherveille
 
177 1748 jeremybenn
          /* 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 876 rherveille
 
181 1748 jeremybenn
          /* set device1 input signals                                  */
182
          device->sigs.pdiagi = pdiagi;
183
          device->sigs.daspi = daspi;
184 876 rherveille
 
185 1748 jeremybenn
          ata_execute_device_diagnostics_cmd (device);
186 876 rherveille
 
187 1748 jeremybenn
          /* clear busy bit                                             */
188
          device->regs.status &= ~ATA_SR_BSY;
189 876 rherveille
 
190 1748 jeremybenn
          /* set DRDY bit, when not a PACKET device                     */
191
          if (!device->conf.packet)
192
            device->regs.status |= ATA_SR_DRDY;
193 876 rherveille
 
194 1748 jeremybenn
          /* set new state                                              */
195
          device->internals.state = ATA_STATE_IDLE;
196
        }
197 1693 nogj
    }
198 1748 jeremybenn
  else if (reset_signal)
199
    {
200
      /* hardware reset signal asserted, stop what we are doing     */
201 876 rherveille
 
202 1748 jeremybenn
      /* 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 876 rherveille
 
209 1748 jeremybenn
      /* set busy bit                                               */
210
      device->regs.status |= ATA_SR_BSY;
211 876 rherveille
 
212 1748 jeremybenn
      /* set new state                                              */
213
      device->internals.state = ATA_STATE_HW_RST;
214
    }
215 1693 nogj
}
216 876 rherveille
 
217
/* power-on and hardware reset                                        */
218 1748 jeremybenn
void
219
ata_devices_hw_reset (struct ata_devices * devices, int reset_signal)
220 876 rherveille
{
221
  /* find device 0                                                    */
222 1748 jeremybenn
  if ((devices->device[0].conf.stream) && (devices->device[1].conf.stream))
223
    {
224
      /* this one is simple, device0 is device0                         */
225 876 rherveille
 
226 1748 jeremybenn
      /* 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 876 rherveille
 
231 1748 jeremybenn
      /* 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 876 rherveille
}
252
 
253 1065 rherveille
 
254 876 rherveille
/*
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 1748 jeremybenn
static void
261
ata_device_do_control_register (struct ata_device * device)
262 876 rherveille
{
263 1748 jeremybenn
  /* TODO respond to new values of nIEN */
264
  /* if device not selected, respond to new values of nIEN & SRST */
265 876 rherveille
 
266
  /* check if SRST bit is set                                         */
267
  if (device->regs.device_control & ATA_DCR_RST)
268 1748 jeremybenn
    {
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 876 rherveille
 
277 1748 jeremybenn
          /* set busy bit                                               */
278
          device->regs.status |= ATA_SR_BSY;
279 876 rherveille
 
280 1748 jeremybenn
          /* set new state                                              */
281
          device->internals.state = ATA_STATE_SW_RST;
282
        }
283 876 rherveille
    }
284 1065 rherveille
  else if (device->internals.state == ATA_STATE_SW_RST)
285 1748 jeremybenn
    {                           /* are we doing a software reset ??                             */
286 876 rherveille
      /* SRST bit cleared, end of software reset                      */
287
 
288
      /*execute device diagnostics                                    */
289 1748 jeremybenn
      ata_execute_device_diagnostics_cmd (device);
290 876 rherveille
 
291
      /* clear busy bit                                               */
292
      device->regs.status &= ~ATA_SR_BSY;
293
 
294
      /* set DRDY bit, when not a PACKET device                       */
295 1748 jeremybenn
      if (!device->conf.packet)
296
        device->regs.status |= ATA_SR_DRDY;
297 876 rherveille
 
298
      /* set new state                                                */
299 1065 rherveille
      device->internals.state = ATA_STATE_IDLE;
300 1748 jeremybenn
    }
301 876 rherveille
  /*
302 1748 jeremybenn
     <else> We are doing a hardware reset (or similar)
303
     ignore command
304
   */
305 876 rherveille
}
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 1748 jeremybenn
static void
312
ata_device_do_command_register (struct ata_device * device)
313 876 rherveille
{
314
  /* check BSY & DRQ                                                  */
315 1748 jeremybenn
  if ((device->regs.status & ATA_SR_BSY)
316
      || (device->regs.status & ATA_SR_DRQ))
317 1751 jeremybenn
    {
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 876 rherveille
 
325
  /* check if device selected                                         */
326 1748 jeremybenn
  if ((device->regs.device_head & ATA_DHR_DEV) == device->internals.dev)
327
    ata_device_execute_cmd (device);
328 876 rherveille
  else
329 1748 jeremybenn
    {
330 876 rherveille
      /* if not selected, only respond to EXECUTE DEVICE DIAGNOSTICS  */
331
      if (device->regs.command == EXECUTE_DEVICE_DIAGNOSTICS)
332 1748 jeremybenn
        ata_device_execute_cmd (device);
333
    }
334 876 rherveille
}
335
 
336
 
337
/*
338
  D E V I C E S _ R E A D
339
*/
340
/* Read from devices                                                  */
341 1748 jeremybenn
short
342
ata_devices_read (struct ata_devices * devices, char adr)
343 876 rherveille
{
344 1748 jeremybenn
  struct ata_device *device;
345 876 rherveille
 
346 1748 jeremybenn
  /* check for no connected devices                                 */
347
  if ((!devices->device[0].conf.stream) && (!devices->device[1].conf.stream))
348 1751 jeremybenn
    {
349
      fprintf (stderr, "Warning: ata_devices_read, no ata devices "
350
               "connected.\n");
351
    }
352 1748 jeremybenn
  else
353 876 rherveille
    {
354
      /* check if both device0 and device1 are connected              */
355 1748 jeremybenn
      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 876 rherveille
      else
365 1748 jeremybenn
        {
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 876 rherveille
 
373
      /* return data provided by selected device                      */
374 1748 jeremybenn
      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 876 rherveille
          else
381 1748 jeremybenn
            {
382
              return 0;          // return 0 when device0 responds for device1
383
            }
384 876 rherveille
 
385 1748 jeremybenn
        case ATA_CHR:
386
          return device->regs.cylinder_high;
387 876 rherveille
 
388 1748 jeremybenn
        case ATA_CLR:
389
          return device->regs.cylinder_low;
390 876 rherveille
 
391 1748 jeremybenn
        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 1705 nogj
              return val;
406 1748 jeremybenn
            }
407 876 rherveille
 
408 1748 jeremybenn
        case ATA_DHR:
409
          return device->regs.device_head;
410 876 rherveille
 
411 1748 jeremybenn
        case ATA_ERR:
412
          return device->regs.error;
413 876 rherveille
 
414 1748 jeremybenn
        case ATA_SCR:
415
          return device->regs.sector_count;
416 876 rherveille
 
417 1748 jeremybenn
        case ATA_SNR:
418
          return device->regs.sector_number;
419 876 rherveille
 
420 1748 jeremybenn
        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 876 rherveille
 
428 1748 jeremybenn
          return 0;              // return 0 when device0 responds for device1
429 1726 nogj
 
430 876 rherveille
//        case ATA_DA   :
431
//          return device -> regs.status;
432 1748 jeremybenn
        }
433 876 rherveille
    }
434 1748 jeremybenn
  return 0;
435 876 rherveille
}
436
 
437
 
438
/*
439
  D E V I C E S _ W R I T E
440
*/
441
/* write to a single device                                           */
442 1748 jeremybenn
static void
443
ata_device_write (struct ata_device * device, char adr, short value)
444 876 rherveille
{
445 1748 jeremybenn
  switch (adr)
446
    {
447
    case ATA_CR:
448
      device->regs.command = value;
449 876 rherveille
 
450 1748 jeremybenn
      /* check command register settings and execute command    */
451
      ata_device_do_command_register (device);
452
      break;
453 876 rherveille
 
454
 
455 1748 jeremybenn
    case ATA_CHR:
456
      device->regs.cylinder_high = value;
457
      break;
458 876 rherveille
 
459 1748 jeremybenn
    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 1705 nogj
            }
477 1748 jeremybenn
        }
478
      device->regs.dataport_i = value;
479
      break;
480 876 rherveille
 
481 1748 jeremybenn
    case ATA_DCR:
482
      device->regs.device_control = value;
483
      ata_device_do_control_register (device);
484
      break;
485 876 rherveille
 
486 1748 jeremybenn
    case ATA_DHR:
487
      device->regs.device_head = value;
488
      break;
489 876 rherveille
 
490 1748 jeremybenn
    case ATA_FR:
491
      device->regs.features = value;
492
      break;
493 876 rherveille
 
494 1748 jeremybenn
    case ATA_SCR:
495
      device->regs.sector_count = value;
496
      break;
497 876 rherveille
 
498 1748 jeremybenn
    case ATA_SNR:
499
      device->regs.sector_number = value;
500
      break;
501 876 rherveille
 
502 1748 jeremybenn
    }                           //endcase
503 876 rherveille
}
504
 
505 1693 nogj
/* Write to devices                                                   */
506 1748 jeremybenn
void
507
ata_devices_write (struct ata_devices * devices, char adr, short value)
508 1693 nogj
{
509
  /* check for no connected devices                                 */
510 1748 jeremybenn
  if (!devices->device[0].conf.stream && !devices->device[1].conf.stream)
511 1751 jeremybenn
    {
512
      fprintf (stderr, "Warning: ata_devices_write, no ata devices "
513
               "connected.\n");
514
    }
515 1748 jeremybenn
  else
516
    {
517
      /* first device                                                 */
518
      if (devices->device[0].conf.stream)
519
        ata_device_write (&devices->device[0], adr, value);
520 1693 nogj
 
521 1748 jeremybenn
      /* second device                                                */
522
      if (devices->device[1].conf.stream)
523
        ata_device_write (&devices->device[1], adr, value);
524
    }
525 1693 nogj
}

powered by: WebSVN 2.1.0

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