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

Subversion Repositories or1k

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

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
  switch(device->type)
126
  {
127
    case TYPE_NO_CONNECT:
128 1488 nogj
      TRACE("ata_device, using type NO_CONNECT.\n");
129 876 rherveille
      device->stream = NULL;
130
      break;
131
 
132
    case TYPE_FILE:
133 1488 nogj
      TRACE("ata_device, using device type FILE.\n");
134 1364 nogj
      device->stream = open_file(&device->size, device->file);
135 876 rherveille
      break;
136
 
137
    case TYPE_LOCAL:
138 1488 nogj
      TRACE("ata_device, using device type LOCAL.\n");
139 876 rherveille
      device->stream = open_local();
140
      break;
141
 
142
    default:
143 1488 nogj
      ERR("Illegal device-type.  Defaulting to type NO_CONNECT.\n");
144 876 rherveille
      device->stream = NULL;
145
      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 1693 nogj
  ata_device_init(&devices->device0, 0);
155 876 rherveille
 
156 1693 nogj
  if(devices->device0.type)
157
    ata_device_init(&devices->device1, ATA_DHR_DEV);
158
  else
159
    ata_device_init(&devices->device1,           0);
160
}
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
      if(!device->packet)
188
        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
  if ( (devices->device0.stream) && (devices->device1.stream) )
219
  {
220
    /* this one is simple, device0 is device0                         */
221
 
222
    /* 1) handle device1 first                                        */
223 1065 rherveille
    ata_device_hw_reset(&devices->device1, reset_signal,
224
                        1,   /* assert dasp, this is device1          */
225
                        0,   /* negate pdiag input, no more devices   */
226 876 rherveille
                        0);  /* negate dasp input, no more devices    */
227
 
228
    /* 2) Then handle device0                                         */
229 1065 rherveille
    ata_device_hw_reset(&devices->device0, reset_signal,
230
                        0,
231
                        devices->device1.sigs.pdiago,
232 876 rherveille
                        devices->device1.sigs.daspo);
233
  }
234
  else if (devices->device0.stream)
235
  {
236
    /* device0 is device0, there's no device1                         */
237 1065 rherveille
    ata_device_hw_reset(&devices->device0, reset_signal,
238
                        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
  }
242
  else if (devices->device1.stream)
243
  {
244
    /* device1 is (logical) device0, there's no (physical) device0    */
245 1065 rherveille
    ata_device_hw_reset(&devices->device1, reset_signal,
246
                        0,   /* negate dasp, this is device0          */
247
                        0,   /* negate pdiag input, there's no device1*/
248 876 rherveille
                        0);  /* negate dasp input, there's no device1 */
249
  }
250
  else
251
  {
252
    /* no devices connected                                           */
253 1488 nogj
    TRACE("ata_device_hw_reset, no devices connected.\n");
254 876 rherveille
  }
255
}
256
 
257 1065 rherveille
 
258 876 rherveille
/*
259
  D E V I C E S _ D O _ C O N T R O L _ R E G I S T E R
260
 
261
  Handles - software reset
262
          - Interrupt enable bit
263
*/
264
void ata_device_do_control_register(ata_device *device)
265
{
266
    /* TODO respond to new values of nIEN */
267
    /* if device not selected, respond to new values of nIEN & SRST */
268
 
269
  /* check if SRST bit is set                                         */
270
  if (device->regs.device_control & ATA_DCR_RST)
271
  {
272 1065 rherveille
    if (device->internals.state == ATA_STATE_IDLE)
273 876 rherveille
    {   /* start software reset                                       */
274
        /* negate bus signals                                         */
275
        device->sigs.pdiago = 0;
276
        device->sigs.intrq  = 0;
277
        device->sigs.iordy  = 0;
278
        device->sigs.dmarq  = 0;
279
 
280
        /* set busy bit                                               */
281
        device->regs.status |= ATA_SR_BSY;
282
 
283
        /* set new state                                              */
284 1065 rherveille
        device->internals.state = ATA_STATE_SW_RST;
285 876 rherveille
 
286
        /* display debug information                                  */
287 1488 nogj
        TRACE("ata_device_sw_reset initiated.\n");
288 876 rherveille
    }
289
  }
290 1065 rherveille
  else if (device->internals.state == ATA_STATE_SW_RST)
291 876 rherveille
  {   /* are we doing a software reset ??                             */
292
      /* SRST bit cleared, end of software reset                      */
293
 
294
      /*execute device diagnostics                                    */
295
      ata_execute_device_diagnostics_cmd(device);
296
 
297
      /* clear busy bit                                               */
298
      device->regs.status &= ~ATA_SR_BSY;
299
 
300
      /* set DRDY bit, when not a PACKET device                       */
301
      if (!device->packet)
302
        device->regs.status |= ATA_SR_DRDY;
303
 
304
      /* set new state                                                */
305 1065 rherveille
      device->internals.state = ATA_STATE_IDLE;
306 876 rherveille
 
307
      /* display debug information                                    */
308 1488 nogj
      TRACE("ata_device_sw_reset done.\n");
309 876 rherveille
  }
310
  /*
311
  <else> We are doing a hardware reset (or similar)
312
         ignore command
313
  */
314
}
315
 
316
 
317
/*
318
  D E V I C E S _ D O _ C O M M A N D _ R E G I S T E R
319
*/
320
void ata_device_do_command_register(ata_device *device)
321
{
322
  /* check BSY & DRQ                                                  */
323
  if ( (device->regs.status & ATA_SR_BSY) || (device->regs.status & ATA_SR_DRQ) )
324
     if (device->regs.command != DEVICE_RESET)
325 1488 nogj
        WARN("ata_device_write, writing a command while BSY or DRQ asserted.");
326 876 rherveille
 
327
  /* check if device selected                                         */
328 1065 rherveille
  if ( (device->regs.device_head & ATA_DHR_DEV) == device->internals.dev )
329 876 rherveille
      ata_device_execute_cmd(device);
330
  else
331
  {
332
      /* if not selected, only respond to EXECUTE DEVICE DIAGNOSTICS  */
333
      if (device->regs.command == EXECUTE_DEVICE_DIAGNOSTICS)
334
          ata_device_execute_cmd(device);
335
  }
336
}
337
 
338
 
339
/*
340
  D E V I C E S _ R E A D
341
*/
342
/* Read from devices                                                  */
343
short ata_devices_read(ata_devices *devices, char adr)
344
{
345
    ata_device *device;
346
 
347
    /* check for no connected devices                                 */
348
    if ( (!devices->device0.stream) && (!devices->device1.stream) )
349 1488 nogj
        ERR("ata_devices_read, no ata devices connected.\n");
350 876 rherveille
    else
351
    {
352
      /* check if both device0 and device1 are connected              */
353
      if ( (devices->device0.stream) && (devices->device1.stream) )
354
      {
355
          /* get the current active device                            */
356
          if (devices->device1.regs.device_head & ATA_DHR_DEV)
357
              device = &devices->device1;
358
          else
359
              device = &devices->device0;
360
      }
361
      else
362
      {
363
          /* only one device connected                                */
364
          if (devices->device1.stream)
365
              device = &devices->device1;
366
          else
367
              device = &devices->device0;
368
      }
369
 
370
      /* return data provided by selected device                      */
371
      switch (adr) {
372
        case ATA_ASR :
373 1488 nogj
          TRACE("alternate_status register read\n");
374 1065 rherveille
          if ( (device->regs.device_head & ATA_DHR_DEV) ==  device->internals.dev )
375 876 rherveille
              return device -> regs.status;
376
          else
377
          {
378 1488 nogj
              TRACE("device0 responds for device1, asr = 0x00\n");
379 876 rherveille
              return 0; // return 0 when device0 responds for device1
380
          }
381
 
382
        case ATA_CHR :
383 1488 nogj
          TRACE("cylinder_high register read, value = 0x%02X\n",
384
                device->regs.cylinder_high);
385 876 rherveille
          return device -> regs.cylinder_high;
386
 
387
        case ATA_CLR :
388 1488 nogj
          TRACE("cylinder_low register read, value = 0x%02X\n",
389 876 rherveille
                 device->regs.cylinder_low);
390
          return device -> regs.cylinder_low;
391
 
392
        case ATA_DR  :
393 1065 rherveille
          if (!device->regs.status & ATA_SR_DRQ)
394
          {
395 1488 nogj
             TRACE("data register read, while DRQ bit negated\n" );
396 1065 rherveille
             return 0;
397
          }
398
          else
399
          {
400 1488 nogj
              TRACE("data register read, value = 0x%04X, cnt = %3d\n",
401
                    *device->internals.dbuf_ptr, device->internals.dbuf_cnt);
402 1065 rherveille
              if (!--device->internals.dbuf_cnt)
403
                   device->regs.status &= ~ATA_SR_DRQ;
404
              return *device -> internals.dbuf_ptr++;
405
          }
406 876 rherveille
 
407
        case ATA_DHR :
408 1488 nogj
          TRACE("device_head register read, value = 0x%02X\n",
409 876 rherveille
                 device->regs.device_head);
410
          return device -> regs.device_head;
411
 
412
        case ATA_ERR :
413 1488 nogj
          TRACE("error register read, value = 0x%02X\n",
414 876 rherveille
                 device->regs.error);
415
          return device -> regs.error;
416
 
417
        case ATA_SCR :
418 1488 nogj
          TRACE("sectorcount register read, value = 0x%02X\n",
419 876 rherveille
                 device->regs.sector_count);
420
          return device -> regs.sector_count;
421
 
422
        case ATA_SNR :
423 1488 nogj
          TRACE("sectornumber register read, value = 0x%02X\n",
424 876 rherveille
                 device->regs.sector_number);
425
          return device -> regs.sector_number;
426
 
427
        case ATA_SR  :
428 1488 nogj
          TRACE("status register read\n");
429 1065 rherveille
          if ( (device->regs.device_head & ATA_DHR_DEV) ==  device->internals.dev)
430 876 rherveille
              return device -> regs.status;
431
          else
432
          {
433 1488 nogj
              TRACE("device0 responds for device1, sr = 0x00\n");
434 876 rherveille
              return 0; // return 0 when device0 responds for device1
435
          }
436
 
437
//        case ATA_DA   :
438
//          return device -> regs.status;
439
      }
440
    }
441 1557 nogj
    return 0;
442 876 rherveille
}
443
 
444
 
445
/*
446
  D E V I C E S _ W R I T E
447
*/
448
/* write to a single device                                           */
449 1693 nogj
static void ata_device_write(ata_device *device, char adr, short value)
450 876 rherveille
{
451
    switch (adr) {
452
        case ATA_CR  :
453
            /*display debug information                               */
454 1488 nogj
            TRACE("command register written, value = 0x%02X\n", value);
455 876 rherveille
 
456
            device->regs.command = value;
457
 
458
            /* check command register settings and execute command    */
459
            ata_device_do_command_register(device);
460
            break;
461
 
462
 
463
        case ATA_CHR :
464
            /*display debug information                               */
465 1488 nogj
            TRACE("cylinder high register written, value = 0x%02X\n", value);
466 876 rherveille
 
467
            device->regs.cylinder_high = value;
468
            break;
469
 
470
        case ATA_CLR :
471
            /*display debug information                               */
472 1488 nogj
            TRACE("cylinder low register written, value = 0x%02X\n", value);
473 876 rherveille
 
474
            device->regs.cylinder_low = value;
475
            break;
476
 
477
        case ATA_DR :
478
            /*display debug information                               */
479 1488 nogj
            TRACE("data register written, value = 0x%04X\n", value);
480 876 rherveille
 
481
            device->regs.dataport_i = value;
482
            break;
483
 
484
        case ATA_DCR :
485
            /*display debug information                               */
486 1488 nogj
            TRACE("device control register written, value = 0x%02X\n", value);
487 876 rherveille
 
488
            device->regs.device_control = value;
489
            ata_device_do_control_register(device);
490
            break;
491
 
492
        case ATA_DHR :
493
            /*display debug information                               */
494 1488 nogj
            TRACE("device head register written, value = 0x%02X\n", value);
495 876 rherveille
 
496
            device->regs.device_head = value;
497
            break;
498
 
499
        case ATA_FR  :
500
            /*display debug information                               */
501 1488 nogj
            TRACE("features register written, value = 0x%02X\n", value);
502 876 rherveille
 
503
            device->regs.features = value;
504
            break;
505
 
506
        case ATA_SCR :
507
            /*display debug information                               */
508 1488 nogj
            TRACE("sectorcount register written, value = 0x%02X\n", value);
509 876 rherveille
 
510
            device->regs.sector_count = value;
511
            break;
512
 
513
        case ATA_SNR :
514
            /*display debug information                               */
515 1488 nogj
            TRACE("sectornumber register written, value = 0x%02X\n", value);
516 876 rherveille
 
517
            device->regs.sector_number = value;
518
            break;
519
 
520
    } //endcase
521
}
522
 
523 1693 nogj
/* Write to devices                                                   */
524
void ata_devices_write(ata_devices *devices, char adr, short value)
525
{
526
  /* check for no connected devices                                 */
527
  if(!devices->device0.stream && !devices->device1.stream)
528
    ERR("ata_devices_write, no ata devices connected.\n");
529
  else {
530
    /* first device                                                 */
531
    if(devices->device0.stream)
532
      ata_device_write(&devices->device0, adr, value);
533
 
534
    /* second device                                                */
535
    if(devices->device1.stream)
536
      ata_device_write(&devices->device1, adr, value);
537
  }
538
}
539
 

powered by: WebSVN 2.1.0

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