4 * Copyright (C) 2004 Jens Axboe <axboe@suse.de>
5 * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org>
7 * Credit goes to Hale Landis for his excellent ata demo software
8 * OF node handling and some fixes by Stefan Reinauer
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
17 #include "libopenbios/bindings.h"
18 #include "kernel/kernel.h"
19 #include "libc/byteorder.h"
20 #include "libc/vsprintf.h"
22 #include "drivers/drivers.h"
27 #include "libopenbios/ofmem.h"
31 #ifdef CONFIG_DEBUG_ESP
32 #define DPRINTF(fmt, args...) \
33 do { printk(fmt , ##args); } while (0)
35 #define DPRINTF(fmt, args...)
39 volatile struct sparc_dma_registers *regs;
40 enum dvma_rev revision;
43 typedef struct sd_private {
45 const char *media_str[2];
54 unsigned char regs[ESP_REG_SIZE];
57 typedef struct esp_private {
58 volatile struct esp_regs *ll;
60 unsigned int irq; /* device IRQ number */
61 struct esp_dma espdma;
62 unsigned char *buffer;
66 static esp_private_t *global_esp;
68 /* DECLARE data structures for the nodes. */
69 DECLARE_UNNAMED_NODE(ob_sd, INSTALL_OPEN, sizeof(sd_private_t *));
70 DECLARE_UNNAMED_NODE(ob_esp, INSTALL_OPEN, sizeof(esp_private_t *));
72 #ifdef CONFIG_DEBUG_ESP
73 static void dump_drive(sd_private_t *drive)
75 printk("SCSI DRIVE @%lx:\n", (unsigned long)drive);
76 printk("id: %d\n", drive->id);
77 printk("media: %s\n", drive->media_str[0]);
78 printk("media: %s\n", drive->media_str[1]);
79 printk("model: %s\n", drive->model);
80 printk("sectors: %d\n", drive->sectors);
81 printk("present: %d\n", drive->present);
82 printk("bs: %d\n", drive->bs);
87 do_command(esp_private_t *esp, sd_private_t *sd, int cmdlen, int replylen)
92 esp->ll->regs[ESP_BUSID] = sd->id & 7;
94 esp->espdma.regs->st_addr = esp->buffer_dvma;
96 esp->ll->regs[ESP_TCLOW] = cmdlen & 0xff;
97 esp->ll->regs[ESP_TCMED] = (cmdlen >> 8) & 0xff;
98 // Set DMA direction and enable DMA
99 esp->espdma.regs->cond_reg = DMA_ENABLE;
100 // Set ATN, issue command
101 esp->ll->regs[ESP_CMD] = ESP_CMD_SELA | ESP_CMD_DMA;
102 // Wait for DMA to complete. Can this fail?
103 while ((esp->espdma.regs->cond_reg & DMA_HNDL_INTR) == 0) /* no-op */;
105 status = esp->ll->regs[ESP_STATUS];
106 // Clear interrupts to avoid guests seeing spurious interrupts
107 (void)esp->ll->regs[ESP_INTRPT];
109 DPRINTF("do_command: id %d, cmd[0] 0x%x, status 0x%x\n", sd->id, esp->buffer[1], status);
111 /* Target didn't want all command data? */
112 if ((status & ESP_STAT_TCNT) != ESP_STAT_TCNT) {
118 /* Target went to status phase instead of data phase? */
119 if ((status & ESP_STAT_PMASK) == ESP_STATP) {
125 esp->espdma.regs->st_addr = esp->buffer_dvma;
127 esp->ll->regs[ESP_TCLOW] = replylen & 0xff;
128 esp->ll->regs[ESP_TCMED] = (replylen >> 8) & 0xff;
130 esp->espdma.regs->cond_reg = DMA_ST_WRITE | DMA_ENABLE;
132 esp->ll->regs[ESP_CMD] = ESP_CMD_TI | ESP_CMD_DMA;
133 // Wait for DMA to complete
134 while ((esp->espdma.regs->cond_reg & DMA_HNDL_INTR) == 0) /* no-op */;
136 status = esp->ll->regs[ESP_STATUS];
137 // Clear interrupts to avoid guests seeing spurious interrupts
138 (void)esp->ll->regs[ESP_INTRPT];
140 DPRINTF("do_command_reply: status 0x%x\n", status);
142 if ((status & ESP_STAT_TCNT) != ESP_STAT_TCNT)
148 // offset is in sectors
150 ob_sd_read_sector(esp_private_t *esp, sd_private_t *sd, int offset)
152 DPRINTF("ob_sd_read_sector id %d sector=%d\n",
155 // Setup command = Read(10)
156 memset(esp->buffer, 0, 11);
157 esp->buffer[0] = 0x80;
158 esp->buffer[1] = READ_10;
160 esp->buffer[3] = (offset >> 24) & 0xff;
161 esp->buffer[4] = (offset >> 16) & 0xff;
162 esp->buffer[5] = (offset >> 8) & 0xff;
163 esp->buffer[6] = offset & 0xff;
168 if (do_command(esp, sd, 11, sd->bs))
175 read_capacity(esp_private_t *esp, sd_private_t *sd)
177 // Setup command = Read Capacity
178 memset(esp->buffer, 0, 11);
179 esp->buffer[0] = 0x80;
180 esp->buffer[1] = READ_CAPACITY;
182 if (do_command(esp, sd, 11, 8)) {
185 DPRINTF("read_capacity id %d failed\n", sd->id);
188 sd->bs = (esp->buffer[4] << 24) | (esp->buffer[5] << 16) | (esp->buffer[6] << 8) | esp->buffer[7];
189 sd->sectors = ((esp->buffer[0] << 24) | (esp->buffer[1] << 16) | (esp->buffer[2] << 8) | esp->buffer[3]) * (sd->bs / 512);
191 DPRINTF("read_capacity id %d bs %d sectors %d\n", sd->id, sd->bs,
197 test_unit_ready(esp_private_t *esp, sd_private_t *sd)
199 /* Setup command = Test Unit Ready */
200 memset(esp->buffer, 0, 7);
201 esp->buffer[0] = 0x80;
202 esp->buffer[1] = TEST_UNIT_READY;
204 if (do_command(esp, sd, 7, 0)) {
205 DPRINTF("test_unit_ready id %d failed\n", sd->id);
209 DPRINTF("test_unit_ready id %d success\n", sd->id);
214 inquiry(esp_private_t *esp, sd_private_t *sd)
216 const char *media[2] = { "UNKNOWN", "UNKNOWN"};
218 // Setup command = Inquiry
219 memset(esp->buffer, 0, 7);
220 esp->buffer[0] = 0x80;
221 esp->buffer[1] = INQUIRY;
225 if (do_command(esp, sd, 7, 36)) {
231 sd->media = esp->buffer[0];
243 sd->media_str[0] = media[0];
244 sd->media_str[1] = media[1];
245 memcpy(sd->model, &esp->buffer[16], 16);
246 sd->model[17] = '\0';
253 ob_sd_read_blocks(sd_private_t **sd)
255 cell n = POP(), cnt = n;
257 char *dest = (char*)POP();
258 int pos, spb, sect_offset;
260 DPRINTF("ob_sd_read_blocks id %d %lx block=%d n=%d\n", (*sd)->id, (unsigned long)dest, blk, n );
262 if ((*sd)->bs == 0) {
266 spb = (*sd)->bs / 512;
268 sect_offset = blk / spb;
269 pos = (blk - sect_offset * spb) * 512;
271 if (ob_sd_read_sector(global_esp, *sd, sect_offset)) {
272 DPRINTF("ob_sd_read_blocks: error\n");
275 while (n && pos < spb * 512) {
276 memcpy(dest, global_esp->buffer + pos, 512);
287 ob_sd_block_size(__attribute__((unused))sd_private_t **sd)
293 ob_sd_open(__attribute__((unused))sd_private_t **sd)
300 POP(); // unit id is 2 ints but we only need one.
301 *sd = &global_esp->sd[id];
303 #ifdef CONFIG_DEBUG_ESP
308 args = pop_fstr_copy();
309 DPRINTF("opening drive %d args %s\n", id, args);
314 selfword("open-deblocker");
316 /* interpose disk-label */
317 ph = find_dev("/packages/disk-label");
326 ob_sd_close(__attribute__((unused)) sd_private_t **sd)
328 selfword("close-deblocker");
331 NODE_METHODS(ob_sd) = {
332 { "open", ob_sd_open },
333 { "close", ob_sd_close },
334 { "read-blocks", ob_sd_read_blocks },
335 { "block-size", ob_sd_block_size },
340 espdma_init(unsigned int slot, uint64_t base, unsigned long offset,
341 struct esp_dma *espdma)
343 espdma->regs = (void *)ofmem_map_io(base + (uint64_t)offset, 0x10);
345 if (espdma->regs == NULL) {
346 DPRINTF("espdma_init: cannot map registers\n");
352 switch ((espdma->regs->cond_reg) & DMA_DEVICE_ID) {
354 espdma->revision = dvmarev0;
355 DPRINTF("Revision 0 ");
358 espdma->revision = dvmaesc1;
359 DPRINTF("ESC Revision 1 ");
362 espdma->revision = dvmarev1;
363 DPRINTF("Revision 1 ");
366 espdma->revision = dvmarev2;
367 DPRINTF("Revision 2 ");
370 espdma->revision = dvmahme;
371 DPRINTF("HME DVMA gate array ");
374 espdma->revision = dvmarevplus;
375 DPRINTF("Revision 1 PLUS ");
378 DPRINTF("unknown dma version %x",
379 (espdma->regs->cond_reg) & DMA_DEVICE_ID);
380 /* espdma->allocated = 1; */
385 push_str("/iommu/sbus/espdma");
386 fword("find-device");
404 ob_esp_initialize(__attribute__((unused)) esp_private_t **esp)
406 phandle_t ph = get_cur_dev();
408 set_int_property(ph, "#address-cells", 2);
409 set_int_property(ph, "#size-cells", 0);
411 /* set device type */
413 fword("device-type");
415 /* QEMU's ESP emulation does not support mixing DMA and FIFO messages. By
416 setting this attribute, we prevent the Solaris ESP kernel driver from
417 trying to use this feature when booting a disk image (and failing) */
420 push_str("scsi-options");
433 ob_esp_decodeunit(__attribute__((unused)) esp_private_t **esp)
435 fword("decode-unit-scsi");
440 ob_esp_encodeunit(__attribute__((unused)) esp_private_t **esp)
442 fword("encode-unit-scsi");
445 NODE_METHODS(ob_esp) = {
446 { NULL, ob_esp_initialize },
447 { "decode-unit", ob_esp_decodeunit },
448 { "encode-unit", ob_esp_encodeunit },
452 add_alias(const char *device, const char *alias)
454 DPRINTF("add_alias dev \"%s\" = alias \"%s\"\n", device, alias);
455 push_str("/aliases");
456 fword("find-device");
458 fword("encode-string");
464 ob_esp_init(unsigned int slot, uint64_t base, unsigned long espoffset,
465 unsigned long dmaoffset)
467 int id, diskcount = 0, cdcount = 0, *counter_ptr;
468 char nodebuff[256], aliasbuff[256];
472 DPRINTF("Initializing SCSI...");
474 esp = malloc(sizeof(esp_private_t));
476 DPRINTF("Can't allocate ESP private structure\n");
482 if (espdma_init(slot, base, dmaoffset, &esp->espdma) != 0) {
485 /* Get the IO region */
486 esp->ll = (void *)ofmem_map_io(base + (uint64_t)espoffset,
487 sizeof(struct esp_regs));
488 if (esp->ll == NULL) {
489 DPRINTF("Can't map ESP registers\n");
493 esp->buffer = (void *)dvma_alloc(BUFSIZE, &esp->buffer_dvma);
494 if (!esp->buffer || !esp->buffer_dvma) {
495 DPRINTF("Can't get a DVMA buffer\n");
500 esp->ll->regs[ESP_CMD] = ESP_CMD_RC;
502 DPRINTF("ESP at 0x%lx, buffer va 0x%lx dva 0x%lx\n", (unsigned long)esp,
503 (unsigned long)esp->buffer, (unsigned long)esp->buffer_dvma);
505 DPRINTF("Initializing SCSI devices...");
507 for (id = 0; id < 8; id++) {
509 if (!inquiry(esp, &esp->sd[id])) {
510 DPRINTF("Unit %d not present\n", id);
513 /* Clear Unit Attention condition from reset */
514 for (i = 0; i < 5; i++) {
515 if (test_unit_ready(esp, &esp->sd[id])) {
520 DPRINTF("Unit %d present but won't become ready\n", id);
523 DPRINTF("Unit %d present\n", id);
524 read_capacity(esp, &esp->sd[id]);
526 #ifdef CONFIG_DEBUG_ESP
527 dump_drive(&esp->sd[id]);
531 REGISTER_NAMED_NODE(ob_esp, "/iommu/sbus/espdma/esp");
534 push_str("/iommu/sbus/espdma/esp");
535 fword("find-device");
549 push_str("clock-frequency");
552 for (id = 0; id < 8; id++) {
553 if (!esp->sd[id].present)
555 push_str("/iommu/sbus/espdma/esp");
556 fword("find-device");
559 fword("device-name");
561 fword("device-type");
562 fword("is-deblocker");
570 fword("finish-device");
571 snprintf(nodebuff, sizeof(nodebuff), "/iommu/sbus/espdma/esp/sd@%d,0",
573 REGISTER_NODE_METHODS(ob_sd, nodebuff);
574 if (esp->sd[id].media == TYPE_ROM) {
575 counter_ptr = &cdcount;
577 counter_ptr = &diskcount;
579 if (*counter_ptr == 0) {
580 add_alias(nodebuff, esp->sd[id].media_str[0]);
581 add_alias(nodebuff, esp->sd[id].media_str[1]);
583 snprintf(aliasbuff, sizeof(aliasbuff), "%s%d",
584 esp->sd[id].media_str[0], *counter_ptr);
585 add_alias(nodebuff, aliasbuff);
586 snprintf(aliasbuff, sizeof(aliasbuff), "%s%d",
587 esp->sd[id].media_str[1], *counter_ptr);
588 add_alias(nodebuff, aliasbuff);
589 snprintf(aliasbuff, sizeof(aliasbuff), "sd(0,%d,0)", id);
590 add_alias(nodebuff, aliasbuff);
591 snprintf(aliasbuff, sizeof(aliasbuff), "sd(0,%d,0)@0,0", id);
592 add_alias(nodebuff, aliasbuff);