ppc64: Don't set Kp bit on SLB
[openbios/afaerber.git] / drivers / esp.c
blob78478f6bcd6374db47e85a3c8d901de66c44570a
1 /*
2 * OpenBIOS ESP driver
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
12 * version 2
16 #include "config.h"
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"
23 #include "asm/io.h"
24 #include "scsi.h"
25 #include "asm/dma.h"
26 #include "esp.h"
27 #include "libopenbios/ofmem.h"
29 #define BUFSIZE 4096
31 #ifdef CONFIG_DEBUG_ESP
32 #define DPRINTF(fmt, args...) \
33 do { printk(fmt , ##args); } while (0)
34 #else
35 #define DPRINTF(fmt, args...)
36 #endif
38 struct esp_dma {
39 volatile struct sparc_dma_registers *regs;
40 enum dvma_rev revision;
43 typedef struct sd_private {
44 unsigned int bs;
45 const char *media_str[2];
46 uint32_t sectors;
47 uint8_t media;
48 uint8_t id;
49 uint8_t present;
50 char model[40];
51 } sd_private_t;
53 struct esp_regs {
54 unsigned char regs[ESP_REG_SIZE];
57 typedef struct esp_private {
58 volatile struct esp_regs *ll;
59 uint32_t buffer_dvma;
60 unsigned int irq; /* device IRQ number */
61 struct esp_dma espdma;
62 unsigned char *buffer;
63 sd_private_t sd[8];
64 } esp_private_t;
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);
84 #endif
86 static int
87 do_command(esp_private_t *esp, sd_private_t *sd, int cmdlen, int replylen)
89 int status;
91 // Set SCSI target
92 esp->ll->regs[ESP_BUSID] = sd->id & 7;
93 // Set DMA address
94 esp->espdma.regs->st_addr = esp->buffer_dvma;
95 // Set DMA length
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 */;
104 // Check status
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[0], status);
111 // Target didn't want all command data or went to status phase
112 // instead of data phase?
113 if ((status & ESP_STAT_TCNT) != ESP_STAT_TCNT
114 || (status & ESP_STAT_PMASK) == ESP_STATP)
115 return status;
117 // Get reply
118 // Set DMA address
119 esp->espdma.regs->st_addr = esp->buffer_dvma;
120 // Set DMA length
121 esp->ll->regs[ESP_TCLOW] = replylen & 0xff;
122 esp->ll->regs[ESP_TCMED] = (replylen >> 8) & 0xff;
123 // Set DMA direction
124 esp->espdma.regs->cond_reg = DMA_ST_WRITE | DMA_ENABLE;
125 // Transfer
126 esp->ll->regs[ESP_CMD] = ESP_CMD_TI | ESP_CMD_DMA;
127 // Wait for DMA to complete
128 while ((esp->espdma.regs->cond_reg & DMA_HNDL_INTR) == 0) /* no-op */;
129 // Check status
130 status = esp->ll->regs[ESP_STATUS];
131 // Clear interrupts to avoid guests seeing spurious interrupts
132 (void)esp->ll->regs[ESP_INTRPT];
134 DPRINTF("do_command_reply: status 0x%x\n", status);
136 if ((status & ESP_STAT_TCNT) != ESP_STAT_TCNT)
137 return status;
138 else
139 return 0; // OK
142 // offset is in sectors
143 static int
144 ob_sd_read_sector(esp_private_t *esp, sd_private_t *sd, int offset)
146 DPRINTF("ob_sd_read_sector id %d sector=%d\n",
147 sd->id, offset);
149 // Setup command = Read(10)
150 memset(esp->buffer, 0, 11);
151 esp->buffer[0] = 0x80;
152 esp->buffer[1] = READ_10;
154 esp->buffer[3] = (offset >> 24) & 0xff;
155 esp->buffer[4] = (offset >> 16) & 0xff;
156 esp->buffer[5] = (offset >> 8) & 0xff;
157 esp->buffer[6] = offset & 0xff;
159 esp->buffer[8] = 0;
160 esp->buffer[9] = 1;
162 if (do_command(esp, sd, 11, sd->bs))
163 return 0;
165 return 0;
168 static unsigned int
169 read_capacity(esp_private_t *esp, sd_private_t *sd)
171 // Setup command = Read Capacity
172 memset(esp->buffer, 0, 11);
173 esp->buffer[0] = 0x80;
174 esp->buffer[1] = READ_CAPACITY;
176 if (do_command(esp, sd, 11, 8)) {
177 sd->sectors = 0;
178 sd->bs = 0;
180 return 0;
182 sd->bs = (esp->buffer[4] << 24) | (esp->buffer[5] << 16) | (esp->buffer[6] << 8) | esp->buffer[7];
183 sd->sectors = ((esp->buffer[0] << 24) | (esp->buffer[1] << 16) | (esp->buffer[2] << 8) | esp->buffer[3]) * (sd->bs / 512);
185 return 1;
188 static unsigned int
189 inquiry(esp_private_t *esp, sd_private_t *sd)
191 const char *media[2] = { "UNKNOWN", "UNKNOWN"};
193 // Setup command = Inquiry
194 memset(esp->buffer, 0, 7);
195 esp->buffer[0] = 0x80;
196 esp->buffer[1] = INQUIRY;
198 esp->buffer[5] = 36;
200 if (do_command(esp, sd, 7, 36)) {
201 sd->present = 0;
202 sd->media = -1;
203 return 0;
205 sd->present = 1;
206 sd->media = esp->buffer[0];
208 switch (sd->media) {
209 case TYPE_DISK:
210 media[0] = "disk";
211 media[1] = "hd";
212 break;
213 case TYPE_ROM:
214 media[0] = "cdrom";
215 media[1] = "cd";
216 break;
218 sd->media_str[0] = media[0];
219 sd->media_str[1] = media[1];
220 memcpy(sd->model, &esp->buffer[16], 16);
221 sd->model[17] = '\0';
223 return 1;
227 static void
228 ob_sd_read_blocks(sd_private_t **sd)
230 cell n = POP(), cnt = n;
231 ucell blk = POP();
232 char *dest = (char*)POP();
233 int pos, spb, sect_offset;
235 DPRINTF("ob_sd_read_blocks id %d %lx block=%d n=%d\n", (*sd)->id, (unsigned long)dest, blk, n );
237 spb = (*sd)->bs / 512;
238 while (n) {
239 sect_offset = blk / spb;
240 pos = (blk - sect_offset * spb) * 512;
242 if (ob_sd_read_sector(global_esp, *sd, sect_offset)) {
243 DPRINTF("ob_sd_read_blocks: error\n");
244 RET(0);
246 while (n && pos < spb * 512) {
247 memcpy(dest, global_esp->buffer + pos, 512);
248 pos += 512;
249 dest += 512;
250 n--;
251 blk++;
254 PUSH(cnt);
257 static void
258 ob_sd_block_size(__attribute__((unused))sd_private_t **sd)
260 PUSH(512);
263 static void
264 ob_sd_open(__attribute__((unused))sd_private_t **sd)
266 int ret = 1, id;
267 phandle_t ph;
269 fword("my-unit");
270 id = POP();
271 POP(); // unit id is 2 ints but we only need one.
272 *sd = &global_esp->sd[id];
274 #ifdef CONFIG_DEBUG_ESP
276 char *args;
278 fword("my-args");
279 args = pop_fstr_copy();
280 DPRINTF("opening drive %d args %s\n", id, args);
281 free(args);
283 #endif
285 selfword("open-deblocker");
287 /* interpose disk-label */
288 ph = find_dev("/packages/disk-label");
289 fword("my-args");
290 PUSH_ph( ph );
291 fword("interpose");
293 RET ( -ret );
296 static void
297 ob_sd_close(__attribute__((unused)) sd_private_t **sd)
299 selfword("close-deblocker");
302 NODE_METHODS(ob_sd) = {
303 { "open", ob_sd_open },
304 { "close", ob_sd_close },
305 { "read-blocks", ob_sd_read_blocks },
306 { "block-size", ob_sd_block_size },
310 static int
311 espdma_init(unsigned int slot, uint64_t base, unsigned long offset,
312 struct esp_dma *espdma)
314 espdma->regs = (void *)ofmem_map_io(base + (uint64_t)offset, 0x10);
316 if (espdma->regs == NULL) {
317 DPRINTF("espdma_init: cannot map registers\n");
318 return -1;
321 DPRINTF("dma1: ");
323 switch ((espdma->regs->cond_reg) & DMA_DEVICE_ID) {
324 case DMA_VERS0:
325 espdma->revision = dvmarev0;
326 DPRINTF("Revision 0 ");
327 break;
328 case DMA_ESCV1:
329 espdma->revision = dvmaesc1;
330 DPRINTF("ESC Revision 1 ");
331 break;
332 case DMA_VERS1:
333 espdma->revision = dvmarev1;
334 DPRINTF("Revision 1 ");
335 break;
336 case DMA_VERS2:
337 espdma->revision = dvmarev2;
338 DPRINTF("Revision 2 ");
339 break;
340 case DMA_VERHME:
341 espdma->revision = dvmahme;
342 DPRINTF("HME DVMA gate array ");
343 break;
344 case DMA_VERSPLUS:
345 espdma->revision = dvmarevplus;
346 DPRINTF("Revision 1 PLUS ");
347 break;
348 default:
349 DPRINTF("unknown dma version %x",
350 (espdma->regs->cond_reg) & DMA_DEVICE_ID);
351 /* espdma->allocated = 1; */
352 break;
354 DPRINTF("\n");
356 push_str("/iommu/sbus/espdma");
357 fword("find-device");
359 /* set reg */
360 PUSH(slot);
361 fword("encode-int");
362 PUSH(offset);
363 fword("encode-int");
364 fword("encode+");
365 PUSH(0x00000010);
366 fword("encode-int");
367 fword("encode+");
368 push_str("reg");
369 fword("property");
371 return 0;
374 static void
375 ob_esp_initialize(__attribute__((unused)) esp_private_t **esp)
377 phandle_t ph = get_cur_dev();
379 set_int_property(ph, "#address-cells", 2);
380 set_int_property(ph, "#size-cells", 0);
382 /* set device type */
383 push_str("scsi");
384 fword("device-type");
386 /* QEMU's ESP emulation does not support mixing DMA and FIFO messages. By
387 setting this attribute, we prevent the Solaris ESP kernel driver from
388 trying to use this feature when booting a disk image (and failing) */
389 PUSH(0x58);
390 fword("encode-int");
391 push_str("scsi-options");
392 fword("property");
394 PUSH(0x24);
395 fword("encode-int");
396 PUSH(0);
397 fword("encode-int");
398 fword("encode+");
399 push_str("intr");
400 fword("property");
403 static void
404 ob_esp_decodeunit(__attribute__((unused)) esp_private_t **esp)
406 fword("decode-unit-scsi");
410 static void
411 ob_esp_encodeunit(__attribute__((unused)) esp_private_t **esp)
413 fword("encode-unit-scsi");
416 NODE_METHODS(ob_esp) = {
417 { NULL, ob_esp_initialize },
418 { "decode-unit", ob_esp_decodeunit },
419 { "encode-unit", ob_esp_encodeunit },
422 static void
423 add_alias(const char *device, const char *alias)
425 DPRINTF("add_alias dev \"%s\" = alias \"%s\"\n", device, alias);
426 push_str("/aliases");
427 fword("find-device");
428 push_str(device);
429 fword("encode-string");
430 push_str(alias);
431 fword("property");
435 ob_esp_init(unsigned int slot, uint64_t base, unsigned long espoffset,
436 unsigned long dmaoffset)
438 int id, diskcount = 0, cdcount = 0, *counter_ptr;
439 char nodebuff[256], aliasbuff[256];
440 esp_private_t *esp;
442 DPRINTF("Initializing SCSI...");
444 esp = malloc(sizeof(esp_private_t));
445 if (!esp) {
446 DPRINTF("Can't allocate ESP private structure\n");
447 return -1;
450 global_esp = esp;
452 if (espdma_init(slot, base, dmaoffset, &esp->espdma) != 0) {
453 return -1;
455 /* Get the IO region */
456 esp->ll = (void *)ofmem_map_io(base + (uint64_t)espoffset,
457 sizeof(struct esp_regs));
458 if (esp->ll == NULL) {
459 DPRINTF("Can't map ESP registers\n");
460 return -1;
463 esp->buffer = (void *)dvma_alloc(BUFSIZE, &esp->buffer_dvma);
464 if (!esp->buffer || !esp->buffer_dvma) {
465 DPRINTF("Can't get a DVMA buffer\n");
466 return -1;
469 // Chip reset
470 esp->ll->regs[ESP_CMD] = ESP_CMD_RC;
472 DPRINTF("ESP at 0x%lx, buffer va 0x%lx dva 0x%lx\n", (unsigned long)esp,
473 (unsigned long)esp->buffer, (unsigned long)esp->buffer_dvma);
474 DPRINTF("done\n");
475 DPRINTF("Initializing SCSI devices...");
477 for (id = 0; id < 8; id++) {
478 esp->sd[id].id = id;
479 if (!inquiry(esp, &esp->sd[id]))
480 continue;
481 read_capacity(esp, &esp->sd[id]);
483 #ifdef CONFIG_DEBUG_ESP
484 dump_drive(&esp->sd[id]);
485 #endif
488 REGISTER_NAMED_NODE(ob_esp, "/iommu/sbus/espdma/esp");
489 device_end();
490 /* set reg */
491 push_str("/iommu/sbus/espdma/esp");
492 fword("find-device");
493 PUSH(slot);
494 fword("encode-int");
495 PUSH(espoffset);
496 fword("encode-int");
497 fword("encode+");
498 PUSH(0x00000010);
499 fword("encode-int");
500 fword("encode+");
501 push_str("reg");
502 fword("property");
504 PUSH(0x02625a00);
505 fword("encode-int");
506 push_str("clock-frequency");
507 fword("property");
509 for (id = 0; id < 8; id++) {
510 if (!esp->sd[id].present)
511 continue;
512 push_str("/iommu/sbus/espdma/esp");
513 fword("find-device");
514 fword("new-device");
515 push_str("sd");
516 fword("device-name");
517 push_str("block");
518 fword("device-type");
519 fword("is-deblocker");
520 PUSH(id);
521 fword("encode-int");
522 PUSH(0);
523 fword("encode-int");
524 fword("encode+");
525 push_str("reg");
526 fword("property");
527 fword("finish-device");
528 snprintf(nodebuff, sizeof(nodebuff), "/iommu/sbus/espdma/esp/sd@%d,0",
529 id);
530 REGISTER_NODE_METHODS(ob_sd, nodebuff);
531 if (esp->sd[id].media == TYPE_ROM) {
532 counter_ptr = &cdcount;
533 } else {
534 counter_ptr = &diskcount;
536 if (*counter_ptr == 0) {
537 add_alias(nodebuff, esp->sd[id].media_str[0]);
538 add_alias(nodebuff, esp->sd[id].media_str[1]);
540 snprintf(aliasbuff, sizeof(aliasbuff), "%s%d",
541 esp->sd[id].media_str[0], *counter_ptr);
542 add_alias(nodebuff, aliasbuff);
543 snprintf(aliasbuff, sizeof(aliasbuff), "%s%d",
544 esp->sd[id].media_str[1], *counter_ptr);
545 add_alias(nodebuff, aliasbuff);
546 snprintf(aliasbuff, sizeof(aliasbuff), "sd(0,%d,0)", id);
547 add_alias(nodebuff, aliasbuff);
548 snprintf(aliasbuff, sizeof(aliasbuff), "sd(0,%d,0)@0,0", id);
549 add_alias(nodebuff, aliasbuff);
550 (*counter_ptr)++;
552 DPRINTF("done\n");
554 return 0;