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

Subversion Repositories or1k

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

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

powered by: WebSVN 2.1.0

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