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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc2/] [or1ksim/] [peripheral/] [atadevice.c] - Blame information for rev 1780

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

powered by: WebSVN 2.1.0

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