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

Subversion Repositories or1k

[/] [or1k/] [tags/] [rel-0-3-0-rc3/] [or1ksim/] [peripheral/] [atadevice.c] - Blame information for rev 1714

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

powered by: WebSVN 2.1.0

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