patch-2.2.14 linux/drivers/scsi/mesh.c
Next file: linux/drivers/scsi/ncr53c8xx.c
Previous file: linux/drivers/scsi/megaraid.h
Back to the patch index
Back to the overall index
- Lines: 154
- Date:
Tue Jan 4 10:12:20 2000
- Orig file:
v2.2.13/linux/drivers/scsi/mesh.c
- Orig date:
Tue Jan 4 11:10:38 2000
diff -u --recursive --new-file v2.2.13/linux/drivers/scsi/mesh.c linux/drivers/scsi/mesh.c
@@ -29,6 +29,10 @@
#include <asm/processor.h>
#include <asm/spinlock.h>
#include <asm/feature.h>
+#ifdef CONFIG_PMAC_PBOOK
+#include <asm/adb.h>
+#include <asm/pmu.h>
+#endif
#include "scsi.h"
#include "hosts.h"
@@ -154,6 +158,8 @@
struct dbdma_cmd *dma_cmds; /* space for dbdma commands, aligned */
int clk_freq;
struct mesh_target tgts[8];
+ struct device_node *dnode;
+ unsigned char *mio_base;
#ifndef MESH_NEW_STYLE_EH
Scsi_Cmnd *completed_q;
Scsi_Cmnd *completed_qtail;
@@ -166,6 +172,14 @@
#endif
};
+#ifdef CONFIG_PMAC_PBOOK
+static int mesh_notify_sleep(struct pmu_sleep_notifier *self, int when);
+static struct pmu_sleep_notifier mesh_sleep_notifier = {
+ mesh_notify_sleep,
+ SLEEP_LEVEL_BLOCK,
+};
+#endif
+
#ifdef MESH_DBG
static void dlog(struct mesh_state *ms, char *fmt, int a);
@@ -213,6 +227,7 @@
static void halt_dma(struct mesh_state *);
static int data_goes_out(Scsi_Cmnd *);
static void do_abort(struct mesh_state *ms);
+static void set_mesh_power(struct mesh_state *ms, int state);
static struct notifier_block mesh_notifier = {
mesh_notify_reboot,
@@ -247,6 +262,7 @@
if (mesh == 0)
mesh = find_compatible_devices("scsi", "chrp,mesh0");
for (; mesh != 0; mesh = mesh->next) {
+ struct device_node *mio;
if (mesh->n_addrs != 2 || mesh->n_intrs != 2) {
printk(KERN_ERR "mesh: expected 2 addrs and 2 intrs"
" (got %d,%d)", mesh->n_addrs, mesh->n_intrs);
@@ -267,6 +283,7 @@
panic("no mesh state");
memset(ms, 0, sizeof(*ms));
ms->host = mesh_host;
+ ms->dnode = mesh;
ms->mesh = (volatile struct mesh_regs *)
ioremap(mesh->addrs[0].address, 0x1000);
ms->dma = (volatile struct dbdma_regs *)
@@ -310,9 +327,16 @@
if (mesh_sync_period < minper)
mesh_sync_period = minper;
- feature_set(mesh, FEATURE_MESH_enable);
- mdelay(200);
+ ms->mio_base = 0;
+ for (mio = ms->dnode->parent; mio; mio = mio->parent)
+ if (strcmp(mio->name, "mac-io") == 0
+ && mio->n_addrs > 0)
+ break;
+ if (mio)
+ ms->mio_base = (unsigned char *)
+ ioremap(mio->addrs[0].address, 0x40);
+ set_mesh_power(ms, 1);
mesh_init(ms);
if (request_irq(ms->meshintr, do_mesh_interrupt, 0, "MESH", ms)) {
@@ -322,11 +346,73 @@
++nmeshes;
}
- if ((_machine == _MACH_Pmac) && (nmeshes > 0))
- register_reboot_notifier(&mesh_notifier);
+ if ((_machine == _MACH_Pmac) && (nmeshes > 0)) {
+#ifdef CONFIG_PMAC_PBOOK
+ pmu_register_sleep_notifier(&mesh_sleep_notifier);
+#endif /* CONFIG_PMAC_PBOOK */
+ register_reboot_notifier(&mesh_notifier);
+ }
return nmeshes;
}
+
+static void
+set_mesh_power(struct mesh_state *ms, int state)
+{
+ if (_machine != _MACH_Pmac || ms->mio_base == 0)
+ return;
+
+ if (state) {
+ feature_set(ms->dnode, FEATURE_MESH_enable);
+ /* This seems to enable the termination power. strangely
+ this doesn't fully agree with OF, but with MacOS */
+ if (ms->mio_base)
+ out_8(ms->mio_base + 0x36, 0x70);
+ mdelay(200);
+ } else {
+ feature_clear(ms->dnode, FEATURE_MESH_enable);
+ if (ms->mio_base)
+ out_8(ms->mio_base + 0x36, 0x34);
+ mdelay(10);
+ }
+}
+
+#ifdef CONFIG_PMAC_PBOOK
+/*
+ * notify clients before sleep and reset bus afterwards
+ */
+int
+mesh_notify_sleep(struct pmu_sleep_notifier *self, int when)
+{
+ struct mesh_state *ms;
+
+ switch (when) {
+ case PBOOK_SLEEP_REQUEST:
+ /* XXX We should wait for current transactions and queue
+ * new ones that would be posted beyond this point
+ */
+ break;
+ case PBOOK_SLEEP_REJECT:
+ break;
+
+ case PBOOK_SLEEP_NOW:
+ for (ms = all_meshes; ms != 0; ms = ms->next) {
+ disable_irq(ms->meshintr);
+ set_mesh_power(ms, 0);
+ }
+ break;
+ case PBOOK_WAKE:
+ for (ms = all_meshes; ms != 0; ms = ms->next) {
+ set_mesh_power(ms, 1);
+ mesh_init(ms);
+ enable_irq(ms->meshintr);
+ }
+ break;
+ }
+ return PBOOK_SLEEP_OK;
+}
+#endif /* CONFIG_PMAC_PBOOK */
+
int
mesh_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)