fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/devices/ata.c *
7 * Created: 2004-12-03 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2004-2018 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27#include "ata.h"
28
29
30#ifndef DEBUG_ATA
31#define DEBUG_ATA 0
32#endif
33
34
35#define ATA_REG_COMMAND 0x07
36#define ATA_REG_STATUS 0x07
37#define ATA_REG_DEVICE_HEAD 0x06
38#define ATA_REG_CYLINDER_HIGH 0x05
39#define ATA_REG_CYLINDER_LOW 0x04
40#define ATA_REG_SECTOR_NUMBER 0x03
41#define ATA_REG_SECTOR_COUNT 0x02
42#define ATA_REG_ERROR 0x01
43#define ATA_REG_FEATURES 0x01
44#define ATA_REG_DATA 0x00
45
46#define ATA_STATUS_BSY 0x80
47#define ATA_STATUS_DRDY 0x40
48#define ATA_STATUS_DF 0x20
49#define ATA_STATUS_DSC 0x10
50#define ATA_STATUS_DRQ 0x08
51#define ATA_STATUS_CORR 0x04
52#define ATA_STATUS_IDX 0x02
53#define ATA_STATUS_ERR 0x01
54
55#define ATA_ERROR_UNC 0x40
56#define ATA_ERROR_MC 0x20
57#define ATA_ERROR_IDNF 0x10
58#define ATA_ERROR_MCR 0x08
59#define ATA_ERROR_ABRT 0x04
60#define ATA_ERROR_TK0NF 0x02
61#define ATA_ERROR_AMNF 0x01
62
63#define ATA_BUF_MODE_NONE 0
64#define ATA_BUF_MODE_READ 1
65#define ATA_BUF_MODE_WRITE 2
66
67#define ATA_CMD_RECALIBRATE 0x10
68#define ATA_CMD_READ 0x20
69#define ATA_CMD_READ_RETRY 0x21
70#define ATA_CMD_WRITE 0x30
71#define ATA_CMD_WRITE_RETRY 0x31
72#define ATA_CMD_DIAGNOSTIC 0x90
73#define ATA_CMD_SET_GEOMETRY 0x91
74#define ATA_CMD_STANDBY_IMMEDIATE1 0x94
75#define ATA_CMD_READ_MULTIPLE 0xc4
76#define ATA_CMD_WRITE_MULTIPLE 0xc5
77#define ATA_CMD_SET_MULTIPLE_MODE 0xc6
78#define ATA_CMD_STANDBY_IMMEDIATE2 0xe0
79#define ATA_CMD_FLUSH_CACHE 0xe7
80#define ATA_CMD_IDENTIFY 0xec
81
82
83unsigned char ata_ctl_get_uint8 (ata_chn_t *ata, unsigned long addr);
84unsigned short ata_ctl_get_uint16 (ata_chn_t *ata, unsigned long addr);
85unsigned long ata_ctl_get_uint32 (ata_chn_t *ata, unsigned long addr);
86
87void ata_ctl_set_uint8 (ata_chn_t *ata, unsigned long addr, unsigned char val);
88void ata_ctl_set_uint16 (ata_chn_t *ata, unsigned long addr, unsigned short val);
89void ata_ctl_set_uint32 (ata_chn_t *ata, unsigned long addr, unsigned long val);
90
91
92void ata_dev_init (ata_dev_t *dev)
93{
94 static unsigned serial = 0;
95
96 dev->chn = NULL;
97
98 dev->blk = NULL;
99
100 dev->reg_cmd = 0;
101 dev->reg_status = ATA_STATUS_DRDY | ATA_STATUS_DSC;
102 dev->reg_features = 0;
103 dev->reg_error = 0;
104 dev->reg_cyl_lo = 0;
105 dev->reg_cyl_hi = 0;
106 dev->reg_head = 0;
107 dev->reg_sec = 0;
108 dev->reg_sec_cnt = 0;
109 dev->reg_dev_ctl = 0;
110
111 dev->c = 0;
112 dev->h = 0;
113 dev->s = 0;
114
115 dev->default_c = 0;
116 dev->default_h = 0;
117 dev->default_s = 0;
118
119 dev->multi_block_max = 0;
120 dev->multi_block_size = 0;
121
122 dev->buf_i = 0;
123 dev->buf_n = 0;
124 dev->buf_m = 0;
125 dev->buf_mult_i = 0;
126 dev->buf_mult_n = 0;
127 dev->buf_mode = ATA_BUF_MODE_NONE;
128 dev->callback = NULL;
129
130 strcpy (dev->model, "PCEDISK");
131 strcpy (dev->firmware, "0");
132 sprintf (dev->serial, "PD%u", serial);
133 serial += 1;
134}
135
136void ata_dev_free (ata_dev_t *dev)
137{
138}
139
140
141void ata_init (ata_chn_t *ata, unsigned long addr1, unsigned long addr2)
142{
143 mem_blk_init (&ata->reg_cmd, addr1, 8, 0);
144 ata->reg_cmd.ext = ata;
145 ata->reg_cmd.get_uint8 = (mem_get_uint8_f) ata_cmd_get_uint8;
146 ata->reg_cmd.get_uint16 = (mem_get_uint16_f) ata_cmd_get_uint16;
147 ata->reg_cmd.get_uint32 = (mem_get_uint32_f) ata_cmd_get_uint32;
148 ata->reg_cmd.set_uint8 = (mem_set_uint8_f) ata_cmd_set_uint8;
149 ata->reg_cmd.set_uint16 = (mem_set_uint16_f) ata_cmd_set_uint16;
150 ata->reg_cmd.set_uint32 = (mem_set_uint32_f) ata_cmd_set_uint32;
151
152 mem_blk_init (&ata->reg_ctl, addr2, 4, 0);
153 ata->reg_ctl.ext = ata;
154 ata->reg_ctl.get_uint8 = (mem_get_uint8_f) ata_ctl_get_uint8;
155 ata->reg_ctl.get_uint16 = (mem_get_uint16_f) ata_ctl_get_uint16;
156 ata->reg_ctl.get_uint32 = (mem_get_uint32_f) ata_ctl_get_uint32;
157 ata->reg_ctl.set_uint8 = (mem_set_uint8_f) ata_ctl_set_uint8;
158 ata->reg_ctl.set_uint16 = (mem_set_uint16_f) ata_ctl_set_uint16;
159 ata->reg_ctl.set_uint32 = (mem_set_uint32_f) ata_ctl_set_uint32;
160
161 ata->irq_val = 0;
162 ata->irq_ext = 0;
163 ata->irq = NULL;
164
165 ata_dev_init (&ata->dev[0]);
166 ata_dev_init (&ata->dev[1]);
167
168 ata->dev[0].chn = ata;
169 ata->dev[1].chn = ata;
170
171 ata->sel = &ata->dev[0];
172}
173
174void ata_free (ata_chn_t *ata)
175{
176 ata_dev_free (&ata->dev[1]);
177 ata_dev_free (&ata->dev[0]);
178
179 mem_blk_free (&ata->reg_ctl);
180 mem_blk_free (&ata->reg_cmd);
181}
182
183ata_chn_t *ata_new (unsigned long addr1, unsigned long addr2)
184{
185 ata_chn_t *ata;
186
187 ata = malloc (sizeof (ata_chn_t));
188 if (ata == NULL) {
189 return (NULL);
190 }
191
192 ata_init (ata, addr1, addr2);
193
194 return (ata);
195}
196
197void ata_del (ata_chn_t *ata)
198{
199 if (ata != NULL) {
200 ata_free (ata);
201 free (ata);
202 }
203}
204
205void ata_set_irq_f (ata_chn_t *ata, void *irq, void *ext)
206{
207 ata->irq = irq;
208 ata->irq_ext = ext;
209}
210
211void ata_set_block (ata_chn_t *ata, disk_t *blk, unsigned devi)
212{
213 ata_dev_t *dev;
214
215 if (devi >= 2) {
216 return;
217 }
218
219 dev = &ata->dev[devi];
220
221 dev->blk = blk;
222
223 dev->default_c = blk->c;
224 dev->default_h = blk->h;
225 dev->default_s = blk->s;
226
227 if (dev->default_h > 16) {
228 dev->default_s = 63;
229 dev->default_h = 16;
230 dev->default_c = dsk_get_block_cnt (blk) / (16UL * 63UL);
231 }
232
233 dev->c = dev->default_c;
234 dev->h = dev->default_h;
235 dev->s = dev->default_s;
236}
237
238void ata_set_model (ata_chn_t *ata, unsigned devi, const char *name)
239{
240 char *dst;
241
242 if (devi < 2) {
243 dst = ata->dev[devi].model;
244 strncpy (dst, name, 64);
245 dst[63] = 0;
246 }
247}
248
249void ata_set_multi_mode (ata_chn_t *ata, unsigned devi, unsigned max)
250{
251 if (max > 255) {
252 max = 255;
253 }
254
255 if (devi < 2) {
256 ata->dev[devi].multi_block_max = max;
257 }
258}
259
260static
261void ata_set_irq (ata_chn_t *ata, unsigned char val)
262{
263 if (ata->sel->reg_dev_ctl & 0x02) {
264 return;
265 }
266
267 val = (val != 0);
268
269 if (val != ata->irq_val) {
270#if DEBUG_ATA >= 3
271 fprintf (stderr, "ata: irq = %d\n", val);
272#endif
273
274 ata->irq_val = val;
275
276 if (ata->irq != NULL) {
277 ata->irq (ata->irq_ext, val);
278 }
279 }
280}
281
282static inline
283unsigned short ata_get_uint16_le (void *buf, unsigned i)
284{
285 unsigned short val;
286 unsigned char *tmp = (unsigned char *) buf + i;
287
288 val = tmp[1];
289 val = (val << 8) | tmp[0];
290
291 return (val);
292}
293
294static inline
295void ata_set_uint16_le (void *buf, unsigned i, unsigned short val)
296{
297 unsigned char *tmp = (unsigned char *) buf + i;
298
299 tmp[0] = val & 0xff;
300 tmp[1] = (val >> 8) & 0xff;
301}
302
303static
304void ata_set_string (void *buf, unsigned i, const char *str, unsigned cnt)
305{
306 unsigned char *tmp = (unsigned char *) buf + i;
307 unsigned char c1, c2;
308
309 while (cnt >= 2) {
310 c1 = (*str == 0) ? ' ' : *(str++);
311 c2 = (*str == 0) ? ' ' : *(str++);
312
313 tmp[0] = c2;
314 tmp[1] = c1;
315
316 tmp += 2;
317 cnt -= 2;
318 }
319
320 if (cnt > 0) {
321 c1 = (*str == 0) ? ' ' : *(str++);
322 tmp[1] = c1;
323 }
324}
325
326
327/* Get the current sector address as LBA */
328static
329int ata_get_lba (ata_dev_t *dev, uint32_t *lba)
330{
331 uint32_t c, h, s;
332
333 if (dev->reg_head & 0x40) {
334 *lba = dev->reg_head & 0x0f;
335 *lba = (*lba << 8) | dev->reg_cyl_hi;
336 *lba = (*lba << 8) | dev->reg_cyl_lo;
337 *lba = (*lba << 8) | dev->reg_sec;
338 }
339 else {
340 c = (dev->reg_cyl_hi << 8) | dev->reg_cyl_lo;
341 h = dev->reg_head & 0x0f;
342 s = dev->reg_sec;
343
344 if ((c >= dev->c) || (h >= dev->h) || (s == 0) || (s > dev->s)) {
345 return (1);
346 }
347
348 *lba = (c * dev->h + h) * dev->s + s - 1;
349 }
350
351 return (0);
352}
353
354
355static
356void ata_cmd_ok (ata_dev_t *dev)
357{
358 dev->reg_status = ATA_STATUS_DRDY | ATA_STATUS_DSC;
359 ata_set_irq (dev->chn, 1);
360}
361
362static
363void ata_cmd_abort (ata_dev_t *dev)
364{
365 dev->reg_status = ATA_STATUS_DRDY | ATA_STATUS_ERR;
366 dev->reg_error = ATA_ERROR_ABRT;
367 ata_set_irq (dev->chn, 1);
368}
369
370static
371void ata_cmd_recalibrate (ata_dev_t *dev)
372{
373#if DEBUG_ATA >= 1
374 fprintf (stderr, "ata: RECALIBRATE\n");
375#endif
376
377 dev->reg_cyl_lo = 0;
378 dev->reg_cyl_hi = 0;
379 dev->reg_head &= 0xf0;
380 dev->reg_sec = (dev->reg_head & 0x40) ? 0 : 1;
381 ata_cmd_ok (dev);
382}
383
384static
385void ata_buf_reset (ata_dev_t *dev)
386{
387 dev->buf_i = 0;
388 dev->buf_n = 0;
389 dev->buf_m = 0;
390
391 dev->buf_blk_i = 0;
392 dev->buf_blk_n = 0;
393
394 dev->buf_mult_i = 0;
395 dev->buf_mult_n = 0;
396
397 dev->buf_mode = ATA_BUF_MODE_NONE;
398}
399
400static
401void ata_cmd_read_cb (ata_dev_t *dev)
402{
403 unsigned cnt;
404
405 /* move to next sector in buffer */
406 dev->buf_i = dev->buf_n;
407 dev->buf_n += 512;
408
409 if (dev->buf_n > dev->buf_m) {
410 if (dev->buf_blk_n == 0) {
411 /* all done */
412 ata_buf_reset (dev);
413
414 dev->reg_status = ATA_STATUS_DRDY | ATA_STATUS_DSC;
415 dev->callback = NULL;
416 return;
417 }
418
419 cnt = ATA_BUF_MAX / 512;
420 if (cnt > dev->buf_blk_n) {
421 cnt = dev->buf_blk_n;
422 }
423
424 while (dsk_read_lba (dev->blk, dev->buf, dev->buf_blk_i, cnt)) {
425 if (cnt == 1) {
426 ata_cmd_abort (dev);
427 return;
428 }
429 cnt = 1;
430 }
431
432 dev->buf_m = 512 * cnt;
433
434 dev->buf_blk_i += cnt;
435 dev->buf_blk_n -= cnt;
436
437 dev->buf_i = 0;
438 dev->buf_n = 512;
439 }
440
441 dev->buf_mode = ATA_BUF_MODE_READ;
442 dev->reg_status = ATA_STATUS_DRDY | ATA_STATUS_DRQ | ATA_STATUS_DSC;
443
444 dev->buf_mult_i += 1;
445
446 if (dev->buf_mult_i >= dev->buf_mult_n) {
447 dev->buf_mult_i = 0;
448 ata_set_irq (dev->chn, 1);
449 }
450}
451
452static
453void ata_cmd_read (ata_dev_t *dev)
454{
455 uint32_t idx;
456
457 if (ata_get_lba (dev, &idx)) {
458 ata_cmd_abort (dev);
459 return;
460 }
461
462#if DEBUG_ATA >= 2
463 fprintf (stderr, "ata: READ (%lu, %u)\n",
464 (unsigned long) idx, dev->reg_sec_cnt
465 );
466#endif
467
468 ata_buf_reset (dev);
469
470 dev->buf_blk_i = idx;
471 dev->buf_blk_n = (dev->reg_sec_cnt == 0) ? 256 : dev->reg_sec_cnt;
472 dev->callback = ata_cmd_read_cb;
473
474 ata_cmd_read_cb (dev);
475}
476
477static
478void ata_cmd_read_multiple (ata_dev_t *dev)
479{
480 uint32_t idx;
481
482 if (dev->multi_block_size == 0) {
483 ata_cmd_abort (dev);
484 return;
485 }
486
487 if (ata_get_lba (dev, &idx)) {
488 ata_cmd_abort (dev);
489 return;
490 }
491
492#if DEBUG_ATA >= 2
493 fprintf (stderr, "ata: READ MULTIPLE (%lu, %u)\n",
494 (unsigned long) idx, dev->reg_sec_cnt
495 );
496#endif
497
498 ata_buf_reset (dev);
499
500 dev->buf_blk_i = idx;
501 dev->buf_blk_n = (dev->reg_sec_cnt == 0) ? 256 : dev->reg_sec_cnt;
502 dev->buf_mult_n = dev->multi_block_size;
503 dev->buf_mult_i = dev->buf_mult_n;
504 dev->callback = ata_cmd_read_cb;
505
506 ata_cmd_read_cb (dev);
507}
508
509static
510void ata_cmd_write_cb (ata_dev_t *dev)
511{
512 unsigned cnt;
513
514 dev->buf_i = dev->buf_n;
515 dev->buf_n += 512;
516
517 if (dev->buf_n > dev->buf_m) {
518 cnt = dev->buf_i / 512;
519
520 if (dsk_write_lba (dev->blk, dev->buf, dev->buf_blk_i, cnt)) {
521 ata_cmd_abort (dev);
522 return;
523 }
524
525 dev->buf_blk_i += cnt;
526 dev->buf_blk_n -= cnt;
527
528 if (dev->buf_blk_n == 0) {
529 ata_buf_reset (dev);
530 dev->callback = NULL;
531 dev->reg_status = ATA_STATUS_DRDY | ATA_STATUS_DSC;
532 ata_set_irq (dev->chn, 1);
533 return;
534 }
535 else {
536 cnt = ATA_BUF_MAX / 512;
537 if (cnt > dev->buf_blk_n) {
538 cnt = dev->buf_blk_n;
539 }
540 dev->buf_i = 0;
541 dev->buf_n = 512;
542 dev->buf_m = 512 * cnt;
543 dev->buf_mode = ATA_BUF_MODE_WRITE;
544 dev->reg_status = ATA_STATUS_DRDY | ATA_STATUS_DRQ | ATA_STATUS_DSC;
545 }
546 }
547
548 dev->buf_mult_i += 1;
549
550 if (dev->buf_mult_i >= dev->buf_mult_n) {
551 dev->buf_mult_i = 0;
552 ata_set_irq (dev->chn, 1);
553 }
554}
555
556static
557void ata_cmd_write (ata_dev_t *dev)
558{
559 unsigned cnt;
560 uint32_t idx;
561
562 if (ata_get_lba (dev, &idx)) {
563 ata_cmd_abort (dev);
564 return;
565 }
566
567#if DEBUG_ATA >= 2
568 fprintf (stderr, "ata: WRITE (%lu, %u)\n",
569 (unsigned long) idx, dev->reg_sec_cnt
570 );
571#endif
572
573 ata_buf_reset (dev);
574
575 dev->buf_i = 0;
576 dev->buf_n = 512;
577
578 dev->buf_mode = ATA_BUF_MODE_WRITE;
579
580 dev->buf_blk_i = idx;
581 dev->buf_blk_n = (dev->reg_sec_cnt == 0) ? 256 : dev->reg_sec_cnt;
582
583 dev->callback = ata_cmd_write_cb;
584
585 cnt = ATA_BUF_MAX / 512;
586 if (cnt > dev->buf_blk_n) {
587 cnt = dev->buf_blk_n;
588 }
589
590 dev->buf_m = 512 * cnt;
591
592 dev->reg_status = ATA_STATUS_DRDY | ATA_STATUS_DRQ | ATA_STATUS_DSC;
593}
594
595static
596void ata_cmd_write_multiple (ata_dev_t *dev)
597{
598 unsigned cnt;
599 uint32_t idx;
600
601 if (ata_get_lba (dev, &idx)) {
602 ata_cmd_abort (dev);
603 return;
604 }
605
606#if DEBUG_ATA >= 2
607 fprintf (stderr, "ata: WRITE MULTIPLE (%lu, %u)\n",
608 (unsigned long) idx, dev->reg_sec_cnt
609 );
610#endif
611
612 ata_buf_reset (dev);
613
614 dev->buf_i = 0;
615 dev->buf_n = 512;
616
617 dev->buf_mode = ATA_BUF_MODE_WRITE;
618
619 dev->buf_blk_i = idx;
620 dev->buf_blk_n = (dev->reg_sec_cnt == 0) ? 256 : dev->reg_sec_cnt;
621 dev->buf_mult_i = 0;
622 dev->buf_mult_n = dev->multi_block_size;
623
624 dev->callback = ata_cmd_write_cb;
625
626 cnt = ATA_BUF_MAX / 512;
627 if (cnt > dev->buf_blk_n) {
628 cnt = dev->buf_blk_n;
629 }
630
631 dev->buf_m = 512 * cnt;
632
633 dev->reg_status = ATA_STATUS_DRDY | ATA_STATUS_DRQ | ATA_STATUS_DSC;
634}
635
636static
637void ata_cmd_set_multiple_mode (ata_dev_t *dev)
638{
639 unsigned cnt;
640
641#if DEBUG_ATA >= 1
642 fprintf (stderr, "ata: SET MULTIPLE MODE (%u)\n",
643 dev->reg_sec_cnt
644 );
645#endif
646
647 cnt = dev->reg_sec_cnt;
648
649 if (cnt > dev->multi_block_max) {
650 ata_cmd_abort (dev);
651 return;
652 }
653
654 dev->multi_block_size = cnt;
655
656 ata_cmd_ok (dev);
657}
658
659static
660void ata_cmd_device_diagnostic (ata_chn_t *ata)
661{
662 unsigned i;
663
664#if DEBUG_ATA >= 1
665 fprintf (stderr, "ata: DEVICE DIAGNOSTIC\n");
666#endif
667
668 for (i = 0; i < 2; i++) {
669 ata->dev[i].reg_cyl_lo = 0;
670 ata->dev[i].reg_cyl_hi = 0;
671 ata->dev[i].reg_sec = 1;
672 ata->dev[i].reg_sec_cnt = 1;
673 ata->dev[i].reg_head = 0;
674 ata->dev[i].reg_error = 0x01;
675 ata->dev[i].reg_status = ATA_STATUS_DRDY | ATA_STATUS_DSC;
676 }
677
678 ata->sel = &ata->dev[0];
679}
680
681static
682void ata_cmd_set_geometry (ata_dev_t *dev)
683{
684 dev->s = (dev->reg_sec_cnt == 0) ? 256 : dev->reg_sec_cnt;
685 dev->h = (dev->reg_head & 0x0f) + 1;
686 dev->c = dsk_get_block_cnt (dev->blk) / ((uint32_t) dev->s * dev->h);
687
688#if DEBUG_ATA >= 1
689 fprintf (stderr, "ata: SET GEOMETRY (%u / %u / %u)\n",
690 dev->c, dev->h, dev->s
691 );
692#endif
693
694 ata_cmd_ok (dev);
695}
696
697static
698void ata_cmd_standby_immediate (ata_dev_t *dev)
699{
700#if DEBUG_ATA >= 1
701 fprintf (stderr, "ata: STANDBY IMMEDIATE\n");
702#endif
703
704 ata_cmd_ok (dev);
705}
706
707static
708void ata_cmd_flush_cache (ata_dev_t *dev)
709{
710#if DEBUG_ATA >= 1
711 fprintf (stderr, "ata: FLUSH CACHE\n");
712#endif
713
714 ata_cmd_ok (dev);
715}
716
717static
718void ata_cmd_identify (ata_dev_t *dev)
719{
720 uint32_t cnt1, cnt2;
721
722#if DEBUG_ATA >= 1
723 fprintf (stderr, "ata: IDENTIFY\n");
724#endif
725
726 memset (dev->buf, 0, 512);
727
728 cnt1 = dev->c * dev->h * dev->s;
729 cnt2 = dsk_get_block_cnt (dev->blk);
730
731 ata_set_uint16_le (dev->buf, 2 * 0, 0x0040);
732 ata_set_uint16_le (dev->buf, 2 * 1, dev->default_c);
733 ata_set_uint16_le (dev->buf, 2 * 3, dev->default_h);
734 ata_set_uint16_le (dev->buf, 2 * 6, dev->default_s);
735 ata_set_string (dev->buf, 2 * 10, dev->serial, 20);
736 ata_set_uint16_le (dev->buf, 2 * 22, 0x0000); /* vendor specific bytes */
737 ata_set_string (dev->buf, 2 * 23, dev->firmware, 8);
738 ata_set_string (dev->buf, 2 * 27, dev->model, 40);
739 ata_set_uint16_le (dev->buf, 2 * 47, dev->multi_block_max & 0xff);
740 ata_set_uint16_le (dev->buf, 2 * 49, 0x0200); /* lba */
741 ata_set_uint16_le (dev->buf, 2 * 53, 0x0001);
742 ata_set_uint16_le (dev->buf, 2 * 54, dev->c);
743 ata_set_uint16_le (dev->buf, 2 * 55, dev->h);
744 ata_set_uint16_le (dev->buf, 2 * 56, dev->s);
745 ata_set_uint16_le (dev->buf, 2 * 57, cnt1 & 0xffff);
746 ata_set_uint16_le (dev->buf, 2 * 58, (cnt1 >> 16) & 0xffff);
747 ata_set_uint16_le (dev->buf, 2 * 60, cnt2 & 0xffff);
748 ata_set_uint16_le (dev->buf, 2 * 61, (cnt2 >> 16) & 0xffff);
749
750 dev->buf_i = 0;
751 dev->buf_n = 512;
752 dev->buf_mode = ATA_BUF_MODE_READ;
753 dev->callback = NULL;
754
755 dev->reg_status = ATA_STATUS_DRQ | 0x50;
756
757 ata_set_irq (dev->chn, 1);
758}
759
760static
761void ata_command (ata_chn_t *ata, unsigned cmd)
762{
763 if (ata->sel->blk == NULL) {
764 ata_cmd_abort (ata->sel);
765 return;
766 }
767
768 switch (cmd) {
769 case ATA_CMD_RECALIBRATE:
770 ata_cmd_recalibrate (ata->sel);
771 break;
772
773 case ATA_CMD_READ:
774 case ATA_CMD_READ_RETRY:
775 ata_cmd_read (ata->sel);
776 break;
777
778 case ATA_CMD_READ_MULTIPLE:
779 ata_cmd_read_multiple (ata->sel);
780 break;
781
782 case ATA_CMD_WRITE:
783 case ATA_CMD_WRITE_RETRY:
784 ata_cmd_write (ata->sel);
785 break;
786
787 case ATA_CMD_WRITE_MULTIPLE:
788 ata_cmd_write_multiple (ata->sel);
789 break;
790
791 case ATA_CMD_SET_MULTIPLE_MODE:
792 ata_cmd_set_multiple_mode (ata->sel);
793 break;
794
795 case ATA_CMD_DIAGNOSTIC:
796 ata_cmd_device_diagnostic (ata);
797 break;
798
799 case ATA_CMD_SET_GEOMETRY:
800 ata_cmd_set_geometry (ata->sel);
801 break;
802
803 case ATA_CMD_STANDBY_IMMEDIATE1:
804 case ATA_CMD_STANDBY_IMMEDIATE2:
805 ata_cmd_standby_immediate (ata->sel);
806 break;
807
808 case ATA_CMD_FLUSH_CACHE:
809 ata_cmd_flush_cache (ata->sel);
810 break;
811
812 case ATA_CMD_IDENTIFY:
813 ata_cmd_identify (ata->sel);
814 break;
815
816 default:
817 fprintf (stderr, "ata: unknown command (%02X)\n", cmd);
818 fflush (stderr);
819 ata_cmd_abort (ata->sel);
820 break;
821 }
822}
823
824static
825unsigned short ata_get_data16 (ata_chn_t *ata)
826{
827 unsigned short val;
828 ata_dev_t *sel;
829
830 sel = ata->sel;
831
832 if (sel->buf_mode != ATA_BUF_MODE_READ) {
833 return (0);
834 }
835
836 val = ata_get_uint16_le (sel->buf, sel->buf_i);
837
838 sel->buf_i += 2;
839 if (sel->buf_i >= sel->buf_n) {
840 if (sel->callback != NULL) {
841 sel->callback (sel);
842 }
843 else {
844 sel->buf_i = 0;
845 sel->buf_n = 0;
846 sel->buf_m = 0;
847 sel->buf_mode = ATA_BUF_MODE_NONE;
848 sel->reg_status = ATA_STATUS_DRDY | ATA_STATUS_DSC;
849 }
850 }
851
852 return (val);
853}
854
855unsigned char ata_cmd_get_uint8 (ata_chn_t *ata, unsigned long addr)
856{
857 ata_dev_t *sel;
858 unsigned char val;
859
860 sel = ata->sel;
861
862 if (sel->blk == NULL) {
863 return (0x00);
864 }
865
866 switch (addr) {
867 case 0x00: /* data */
868 val = 0;
869 break;
870
871 case 0x01: /* error */
872 val = sel->reg_error;
873 break;
874
875 case 0x02: /* sector count */
876 val = sel->reg_sec_cnt;
877 break;
878
879 case 0x03: /* sector number */
880 val = sel->reg_sec;
881 break;
882
883 case 0x04: /* cylinder low */
884 val = sel->reg_cyl_lo;
885 break;
886
887 case 0x05: /* cylinder high */
888 val = sel->reg_cyl_hi;
889 break;
890
891 case 0x06: /* device / head */
892 val = sel->reg_head;
893 break;
894
895 case 0x07: /* status */
896 ata_set_irq (ata, 0);
897 val = sel->reg_status;
898 break;
899
900 default:
901 val = 0xff;
902 break;
903 }
904
905#if DEBUG_ATA >= 2
906 fprintf (stderr, "ata: get8 %08lX -> %02X\n", addr, val);
907 fflush (stderr);
908#endif
909
910 return (val);
911}
912
913unsigned short ata_cmd_get_uint16 (ata_chn_t *ata, unsigned long addr)
914{
915 if (addr == 0) {
916 return (ata_get_data16 (ata));
917 }
918
919 return (ata_cmd_get_uint8 (ata, addr));
920}
921
922unsigned long ata_cmd_get_uint32 (ata_chn_t *ata, unsigned long addr)
923{
924 return (ata_cmd_get_uint8 (ata, addr));
925}
926
927static
928void ata_set_data16 (ata_chn_t *ata, unsigned short val)
929{
930 ata_dev_t *sel;
931
932 sel = ata->sel;
933
934 if (sel->buf_mode != ATA_BUF_MODE_WRITE) {
935 return;
936 }
937
938 ata_set_uint16_le (sel->buf, sel->buf_i, val);
939
940 sel->buf_i += 2;
941 if (sel->buf_i >= sel->buf_n) {
942 if (sel->callback != NULL) {
943 sel->callback (sel);
944 }
945 else {
946 ata_buf_reset (sel);
947 sel->reg_status = ATA_STATUS_DRDY | ATA_STATUS_DSC;
948 }
949 }
950}
951
952void ata_cmd_set_uint8 (ata_chn_t *ata, unsigned long addr, unsigned char val)
953{
954#if DEBUG_ATA >= 2
955 fprintf (stderr, "ata: set8 %08lX <- %02X\n", addr, val);
956 fflush (stderr);
957#endif
958
959 switch (addr) {
960 case 0x00: /* data */
961 break;
962
963 case 0x01: /* features */
964 ata->dev[0].reg_features = val;
965 ata->dev[1].reg_features = val;
966 break;
967
968 case 0x02: /* sector count */
969 ata->dev[0].reg_sec_cnt = val;
970 ata->dev[1].reg_sec_cnt = val;
971 break;
972
973 case 0x03: /* sector number */
974 ata->dev[0].reg_sec = val;
975 ata->dev[1].reg_sec = val;
976 break;
977
978 case 0x04: /* cylinder low */
979 ata->dev[0].reg_cyl_lo = val;
980 ata->dev[1].reg_cyl_lo = val;
981 break;
982
983 case 0x05: /* cylinder high */
984 ata->dev[0].reg_cyl_hi = val;
985 ata->dev[1].reg_cyl_hi = val;
986 break;
987
988 case 0x06: /* device / head */
989 ata->dev[0].reg_head = val;
990 ata->dev[1].reg_head = val;
991 ata->sel = &ata->dev[(val & 0x10) ? 1 : 0];
992 break;
993
994 case 0x07: /* command */
995 ata_command (ata, val);
996 break;
997 }
998}
999
1000void ata_cmd_set_uint16 (ata_chn_t *ata, unsigned long addr, unsigned short val)
1001{
1002 if (addr == 0) {
1003 ata_set_data16 (ata, val);
1004 }
1005}
1006
1007void ata_cmd_set_uint32 (ata_chn_t *ata, unsigned long addr, unsigned long val)
1008{
1009}
1010
1011
1012unsigned char ata_ctl_get_uint8 (ata_chn_t *ata, unsigned long addr)
1013{
1014 unsigned char val;
1015
1016 switch (addr) {
1017 case 0x02: /* alternate status */
1018 val = ata->sel->reg_status;
1019 break;
1020
1021 default:
1022 val = 0;
1023 break;
1024 }
1025
1026#if DEBUG_ATA >= 2
1027 fprintf (stderr, "ata: get ctl8 %08lX -> %02X\n", addr, val);
1028 fflush (stderr);
1029#endif
1030
1031 return (val);
1032}
1033
1034unsigned short ata_ctl_get_uint16 (ata_chn_t *ata, unsigned long addr)
1035{
1036 return (ata_ctl_get_uint8 (ata, addr));
1037}
1038
1039unsigned long ata_ctl_get_uint32 (ata_chn_t *ata, unsigned long addr)
1040{
1041 return (ata_ctl_get_uint8 (ata, addr));
1042}
1043
1044void ata_ctl_set_uint8 (ata_chn_t *ata, unsigned long addr, unsigned char val)
1045{
1046#if DEBUG_ATA >= 2
1047 fprintf (stderr, "ata: set ctl8 %08lX <- %02X\n", addr, val);
1048 fflush (stderr);
1049#endif
1050
1051 switch (addr) {
1052 case 0x02:
1053 if ((ata->sel->reg_dev_ctl ^ val) & ~val & 0x04) {
1054 /* reset 1 -> 0 */
1055 unsigned i;
1056
1057 for (i = 0; i < 2; i++) {
1058 ata->dev[i].reg_cyl_lo = 0;
1059 ata->dev[i].reg_cyl_hi = 0;
1060 ata->dev[i].reg_sec = 1;
1061 ata->dev[i].reg_sec_cnt = 1;
1062 ata->dev[i].reg_head = 0;
1063 ata->dev[i].reg_error = 0x01;
1064 ata->dev[i].reg_status = ATA_STATUS_DRDY | ATA_STATUS_DSC;
1065 }
1066
1067 ata->sel = &ata->dev[0];
1068 }
1069
1070 if (val & 0x02) {
1071 ata_set_irq (ata, 0);
1072 }
1073
1074 ata->dev[0].reg_dev_ctl = val;
1075 ata->dev[1].reg_dev_ctl = val;
1076 break;
1077 }
1078}
1079
1080void ata_ctl_set_uint16 (ata_chn_t *ata, unsigned long addr, unsigned short val)
1081{
1082}
1083
1084void ata_ctl_set_uint32 (ata_chn_t *ata, unsigned long addr, unsigned long val)
1085{
1086}