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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc3/] [or1ksim/] [peripheral/] [atadevice.c] - Blame information for rev 1308

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

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

powered by: WebSVN 2.1.0

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