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 1695

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
/*
333
  D E V I C E S _ R E A D
334
*/
335
/* Read from devices                                                  */
336
short ata_devices_read(ata_devices *devices, char adr)
337
{
338
    ata_device *device;
339
 
340
    /* check for no connected devices                                 */
341 1695 nogj
    if((!devices->device[0].conf.stream) && (!devices->device[1].conf.stream))
342 1488 nogj
        ERR("ata_devices_read, no ata devices connected.\n");
343 876 rherveille
    else
344
    {
345
      /* check if both device0 and device1 are connected              */
346 1695 nogj
      if((devices->device[0].conf.stream) && (devices->device[1].conf.stream)) {
347 876 rherveille
          /* get the current active device                            */
348 1694 nogj
          if (devices->device[1].regs.device_head & ATA_DHR_DEV)
349
              device = &devices->device[1];
350 876 rherveille
          else
351 1694 nogj
              device = &devices->device[0];
352 876 rherveille
      }
353
      else
354
      {
355
          /* only one device connected                                */
356 1695 nogj
          if(devices->device[1].conf.stream)
357 1694 nogj
              device = &devices->device[1];
358 876 rherveille
          else
359 1694 nogj
              device = &devices->device[0];
360 876 rherveille
      }
361
 
362
      /* return data provided by selected device                      */
363
      switch (adr) {
364
        case ATA_ASR :
365 1488 nogj
          TRACE("alternate_status register read\n");
366 1065 rherveille
          if ( (device->regs.device_head & ATA_DHR_DEV) ==  device->internals.dev )
367 876 rherveille
              return device -> regs.status;
368
          else
369
          {
370 1488 nogj
              TRACE("device0 responds for device1, asr = 0x00\n");
371 876 rherveille
              return 0; // return 0 when device0 responds for device1
372
          }
373
 
374
        case ATA_CHR :
375 1488 nogj
          TRACE("cylinder_high register read, value = 0x%02X\n",
376
                device->regs.cylinder_high);
377 876 rherveille
          return device -> regs.cylinder_high;
378
 
379
        case ATA_CLR :
380 1488 nogj
          TRACE("cylinder_low register read, value = 0x%02X\n",
381 876 rherveille
                 device->regs.cylinder_low);
382
          return device -> regs.cylinder_low;
383
 
384
        case ATA_DR  :
385 1065 rherveille
          if (!device->regs.status & ATA_SR_DRQ)
386
          {
387 1488 nogj
             TRACE("data register read, while DRQ bit negated\n" );
388 1065 rherveille
             return 0;
389
          }
390
          else
391
          {
392 1488 nogj
              TRACE("data register read, value = 0x%04X, cnt = %3d\n",
393
                    *device->internals.dbuf_ptr, device->internals.dbuf_cnt);
394 1065 rherveille
              if (!--device->internals.dbuf_cnt)
395
                   device->regs.status &= ~ATA_SR_DRQ;
396
              return *device -> internals.dbuf_ptr++;
397
          }
398 876 rherveille
 
399
        case ATA_DHR :
400 1488 nogj
          TRACE("device_head register read, value = 0x%02X\n",
401 876 rherveille
                 device->regs.device_head);
402
          return device -> regs.device_head;
403
 
404
        case ATA_ERR :
405 1488 nogj
          TRACE("error register read, value = 0x%02X\n",
406 876 rherveille
                 device->regs.error);
407
          return device -> regs.error;
408
 
409
        case ATA_SCR :
410 1488 nogj
          TRACE("sectorcount register read, value = 0x%02X\n",
411 876 rherveille
                 device->regs.sector_count);
412
          return device -> regs.sector_count;
413
 
414
        case ATA_SNR :
415 1488 nogj
          TRACE("sectornumber register read, value = 0x%02X\n",
416 876 rherveille
                 device->regs.sector_number);
417
          return device -> regs.sector_number;
418
 
419
        case ATA_SR  :
420 1488 nogj
          TRACE("status register read\n");
421 1065 rherveille
          if ( (device->regs.device_head & ATA_DHR_DEV) ==  device->internals.dev)
422 876 rherveille
              return device -> regs.status;
423
          else
424
          {
425 1488 nogj
              TRACE("device0 responds for device1, sr = 0x00\n");
426 876 rherveille
              return 0; // return 0 when device0 responds for device1
427
          }
428
 
429
//        case ATA_DA   :
430
//          return device -> regs.status;
431
      }
432
    }
433 1557 nogj
    return 0;
434 876 rherveille
}
435
 
436
 
437
/*
438
  D E V I C E S _ W R I T E
439
*/
440
/* write to a single device                                           */
441 1693 nogj
static void ata_device_write(ata_device *device, char adr, short value)
442 876 rherveille
{
443
    switch (adr) {
444
        case ATA_CR  :
445
            /*display debug information                               */
446 1488 nogj
            TRACE("command register written, value = 0x%02X\n", value);
447 876 rherveille
 
448
            device->regs.command = value;
449
 
450
            /* check command register settings and execute command    */
451
            ata_device_do_command_register(device);
452
            break;
453
 
454
 
455
        case ATA_CHR :
456
            /*display debug information                               */
457 1488 nogj
            TRACE("cylinder high register written, value = 0x%02X\n", value);
458 876 rherveille
 
459
            device->regs.cylinder_high = value;
460
            break;
461
 
462
        case ATA_CLR :
463
            /*display debug information                               */
464 1488 nogj
            TRACE("cylinder low register written, value = 0x%02X\n", value);
465 876 rherveille
 
466
            device->regs.cylinder_low = value;
467
            break;
468
 
469
        case ATA_DR :
470
            /*display debug information                               */
471 1488 nogj
            TRACE("data register written, value = 0x%04X\n", value);
472 876 rherveille
 
473
            device->regs.dataport_i = value;
474
            break;
475
 
476
        case ATA_DCR :
477
            /*display debug information                               */
478 1488 nogj
            TRACE("device control register written, value = 0x%02X\n", value);
479 876 rherveille
 
480
            device->regs.device_control = value;
481
            ata_device_do_control_register(device);
482
            break;
483
 
484
        case ATA_DHR :
485
            /*display debug information                               */
486 1488 nogj
            TRACE("device head register written, value = 0x%02X\n", value);
487 876 rherveille
 
488
            device->regs.device_head = value;
489
            break;
490
 
491
        case ATA_FR  :
492
            /*display debug information                               */
493 1488 nogj
            TRACE("features register written, value = 0x%02X\n", value);
494 876 rherveille
 
495
            device->regs.features = value;
496
            break;
497
 
498
        case ATA_SCR :
499
            /*display debug information                               */
500 1488 nogj
            TRACE("sectorcount register written, value = 0x%02X\n", value);
501 876 rherveille
 
502
            device->regs.sector_count = value;
503
            break;
504
 
505
        case ATA_SNR :
506
            /*display debug information                               */
507 1488 nogj
            TRACE("sectornumber register written, value = 0x%02X\n", value);
508 876 rherveille
 
509
            device->regs.sector_number = value;
510
            break;
511
 
512
    } //endcase
513
}
514
 
515 1693 nogj
/* Write to devices                                                   */
516
void ata_devices_write(ata_devices *devices, char adr, short value)
517
{
518
  /* check for no connected devices                                 */
519 1695 nogj
  if(!devices->device[0].conf.stream && !devices->device[1].conf.stream)
520 1693 nogj
    ERR("ata_devices_write, no ata devices connected.\n");
521
  else {
522
    /* first device                                                 */
523 1695 nogj
    if(devices->device[0].conf.stream)
524 1694 nogj
      ata_device_write(&devices->device[0], adr, value);
525 1693 nogj
 
526
    /* second device                                                */
527 1695 nogj
    if(devices->device[1].conf.stream)
528 1694 nogj
      ata_device_write(&devices->device[1], adr, value);
529 1693 nogj
  }
530
}
531
 

powered by: WebSVN 2.1.0

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