summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ppbus/immio.c102
-rw-r--r--sys/dev/ppbus/vpoio.c172
-rw-r--r--sys/dev/ppbus/vpoio.h7
3 files changed, 98 insertions, 183 deletions
diff --git a/sys/dev/ppbus/immio.c b/sys/dev/ppbus/immio.c
index dd8a0c9..05665f00 100644
--- a/sys/dev/ppbus/immio.c
+++ b/sys/dev/ppbus/immio.c
@@ -372,14 +372,34 @@ imm_detect(struct vpoio_data *vpo)
/* disconnect the drive, keep the bus */
imm_disconnect(vpo, NULL, 0);
- /* we already have the bus, just connect */
- imm_connect(vpo, PPB_DONTWAIT, &error, 0);
+ vpo->vpo_mode_found = VP0_MODE_UNDEFINED;
+ error = 1;
+ /* try to enter EPP mode since vpoio failure put the bus in NIBBLE */
+ if (ppb_set_mode(ppbus, PPB_EPP) != -1) {
+ imm_connect(vpo, PPB_DONTWAIT, &error, 0);
+ }
+
+ /* if connection failed try PS/2 then NIBBLE modes */
if (error) {
- if (bootverbose)
- printf("imm%d: can't connect to the drive\n",
- vpo->vpo_unit);
- goto error;
+ if (ppb_set_mode(ppbus, PPB_PS2) != -1) {
+ imm_connect(vpo, PPB_DONTWAIT, &error, 0);
+ }
+ if (error) {
+ if (ppb_set_mode(ppbus, PPB_NIBBLE) != -1) {
+ imm_connect(vpo, PPB_DONTWAIT, &error, 0);
+ if (error)
+ goto error;
+ vpo->vpo_mode_found = VP0_MODE_NIBBLE;
+ } else {
+ printf("imm%d: NIBBLE mode unavailable!\n", vpo->vpo_unit);
+ goto error;
+ }
+ } else {
+ vpo->vpo_mode_found = VP0_MODE_PS2;
+ }
+ } else {
+ vpo->vpo_mode_found = VP0_MODE_EPP;
}
/* send SCSI reset signal */
@@ -554,7 +574,6 @@ int
imm_attach(struct vpoio_data *vpo)
{
device_t ppbus = device_get_parent(vpo->vpo_dev);
- int epp;
/*
* Initialize microsequence code
@@ -576,64 +595,25 @@ imm_attach(struct vpoio_data *vpo)
*/
ppb_request_bus(ppbus, vpo->vpo_dev, PPB_WAIT);
- /* enter NIBBLE mode to configure submsq */
- if (ppb_set_mode(ppbus, PPB_NIBBLE) != -1) {
-
- ppb_MS_GET_init(ppbus, vpo->vpo_dev, vpo->vpo_nibble_inbyte_msq);
- ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq);
- }
-
- /* enter PS2 mode to configure submsq */
- if (ppb_set_mode(ppbus, PPB_PS2) != -1) {
-
+ /* ppbus automatically restore the last mode entered during detection */
+ switch (vpo->vpo_mode_found) {
+ case VP0_MODE_EPP:
+ ppb_MS_GET_init(ppbus, vpo->vpo_dev, epp17_instr);
+ ppb_MS_PUT_init(ppbus, vpo->vpo_dev, epp17_outstr);
+ printf("imm%d: EPP mode\n", vpo->vpo_unit);
+ break;
+ case VP0_MODE_PS2:
ppb_MS_GET_init(ppbus, vpo->vpo_dev, ps2_inbyte_submicroseq);
ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq);
- }
-
- epp = ppb_get_epp_protocol(ppbus);
-
- /* enter EPP mode to configure submsq */
- if (ppb_set_mode(ppbus, PPB_EPP) != -1) {
-
- switch (epp) {
- case EPP_1_9:
- case EPP_1_7:
- ppb_MS_GET_init(ppbus, vpo->vpo_dev, epp17_instr);
- ppb_MS_PUT_init(ppbus, vpo->vpo_dev, epp17_outstr);
- break;
- default:
- panic("%s: unknown EPP protocol (0x%x)", __FUNCTION__,
- epp);
- }
- }
-
- /* try to enter EPP or PS/2 mode, NIBBLE otherwise */
- if (ppb_set_mode(ppbus, PPB_EPP) != -1) {
- switch (epp) {
- case EPP_1_9:
- printf("imm%d: EPP 1.9 mode\n", vpo->vpo_unit);
- break;
- case EPP_1_7:
- printf("imm%d: EPP 1.7 mode\n", vpo->vpo_unit);
- break;
- default:
- panic("%s: unknown EPP protocol (0x%x)", __FUNCTION__,
- epp);
- }
- } else if (ppb_set_mode(ppbus, PPB_PS2) != -1)
printf("imm%d: PS2 mode\n", vpo->vpo_unit);
-
- else if (ppb_set_mode(ppbus, PPB_NIBBLE) != -1)
+ break;
+ case VP0_MODE_NIBBLE:
+ ppb_MS_GET_init(ppbus, vpo->vpo_dev, vpo->vpo_nibble_inbyte_msq);
+ ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq);
printf("imm%d: NIBBLE mode\n", vpo->vpo_unit);
-
- else {
- printf("imm%d: can't enter NIBBLE, PS2 or EPP mode\n",
- vpo->vpo_unit);
-
- ppb_release_bus(ppbus, vpo->vpo_dev);
-
- free(vpo->vpo_nibble_inbyte_msq, M_DEVBUF);
- return (ENXIO);
+ break;
+ default:
+ panic("imm: unknown mode %d", vpo->vpo_mode_found);
}
ppb_release_bus(ppbus, vpo->vpo_dev);
diff --git a/sys/dev/ppbus/vpoio.c b/sys/dev/ppbus/vpoio.c
index 6610977..c8fd273 100644
--- a/sys/dev/ppbus/vpoio.c
+++ b/sys/dev/ppbus/vpoio.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1998, 1999 Nicolas Souchu
+ * Copyright (c) 2000 Alcove - Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -364,24 +365,38 @@ vpoio_detect(struct vpoio_data *vpo)
return (error);
ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret);
+ /* Force disconnection */
- if (PPB_IN_EPP_MODE(ppbus))
+ /* Try to enter EPP mode, then connect to the drive in EPP mode */
+ if (ppb_set_mode(ppbus, PPB_EPP) != -1) {
+ /* call manually the microseq instead of using the appropriate function
+ * since we already requested the ppbus */
ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_epp_microseq, &ret);
- else
- ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret);
+ }
- ppb_MS_microseq(ppbus, vpo->vpo_dev, in_disk_mode, &ret);
- if (!ret) {
+ /* If EPP mode switch failed or ZIP connection in EPP mode failed,
+ * try to connect in NIBBLE mode */
+ if (!vpoio_in_disk_mode(vpo)) {
- /* try spp mode (maybe twice or because previous mode was PS2)
- * NIBBLE mode will be restored on next transfers if detection
- * succeed
+ /* The interface must be at least PS/2 or NIBBLE capable.
+ * There is no way to know if the ZIP will work with
+ * PS/2 mode since PS/2 and SPP both use the same connect
+ * sequence. One must supress PS/2 with boot flags if
+ * PS/2 mode fails (see ppc(4)).
*/
- ppb_set_mode(ppbus, PPB_NIBBLE);
- ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret);
+ if (ppb_set_mode(ppbus, PPB_PS2) != -1) {
+ vpo->vpo_mode_found = VP0_MODE_PS2;
+ } else {
+ if (ppb_set_mode(ppbus, PPB_NIBBLE) == -1)
+ goto error;
+
+ vpo->vpo_mode_found = VP0_MODE_NIBBLE;
+ }
- ppb_MS_microseq(ppbus, vpo->vpo_dev, in_disk_mode, &ret);
- if (!ret) {
+ /* Can't know if the interface is capable of PS/2 yet */
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret);
+ if (!vpoio_in_disk_mode(vpo)) {
+ vpo->vpo_mode_found = VP0_MODE_UNDEFINED;
if (bootverbose)
printf("vpo%d: can't connect to the drive\n",
vpo->vpo_unit);
@@ -391,6 +406,8 @@ vpoio_detect(struct vpoio_data *vpo)
&ret);
goto error;
}
+ } else {
+ vpo->vpo_mode_found = VP0_MODE_EPP;
}
/* send SCSI reset signal */
@@ -400,9 +417,7 @@ vpoio_detect(struct vpoio_data *vpo)
/* ensure we are disconnected or daisy chained peripheral
* may cause serious problem to the disk */
-
- ppb_MS_microseq(ppbus, vpo->vpo_dev, in_disk_mode, &ret);
- if (ret) {
+ if (vpoio_in_disk_mode(vpo)) {
if (bootverbose)
printf("vpo%d: can't disconnect from the drive\n",
vpo->vpo_unit);
@@ -429,28 +444,6 @@ vpoio_outstr(struct vpoio_data *vpo, char *buffer, int size)
ppb_MS_exec(ppbus, vpo->vpo_dev, MS_OP_PUT, (union ppb_insarg)buffer,
(union ppb_insarg)size, (union ppb_insarg)MS_UNKNOWN, &error);
-#if 0
- /* XXX EPP 1.9 not implemented with microsequences */
- else {
-
- ppb_reset_epp_timeout(ppbus);
- ppb_wctr(ppbus, H_AUTO | H_SELIN | H_INIT | H_STROBE);
-
- if (((long) buffer | size) & 0x03)
- ppb_outsb_epp(ppbus,
- buffer, size);
- else
- ppb_outsl_epp(ppbus,
- buffer, size/4);
-
- if ((ppb_rstr(ppbus) & TIMEOUT)) {
- error = VP0_EPPDATA_TIMEOUT;
- goto error;
- }
-
- ppb_wctr(ppbus, H_AUTO | H_nSELIN | H_INIT | H_STROBE);
- }
-#endif
ppb_ecp_sync(ppbus);
return (error);
@@ -468,30 +461,6 @@ vpoio_instr(struct vpoio_data *vpo, char *buffer, int size)
ppb_MS_exec(ppbus, vpo->vpo_dev, MS_OP_GET, (union ppb_insarg)buffer,
(union ppb_insarg)size, (union ppb_insarg)MS_UNKNOWN, &error);
-#if 0
- /* XXX EPP 1.9 not implemented with microsequences */
- else {
-
- ppb_reset_epp_timeout(ppbus);
- ppb_wctr(ppbus, PCD |
- H_AUTO | H_SELIN | H_INIT | H_STROBE);
-
- if (((long) buffer | size) & 0x03)
- ppb_insb_epp(ppbus,
- buffer, size);
- else
- ppb_insl_epp(ppbus,
- buffer, size/4);
-
- if ((ppb_rstr(ppbus) & TIMEOUT)) {
- error = VP0_EPPDATA_TIMEOUT;
- goto error;
- }
-
- ppb_wctr(ppbus, PCD |
- H_AUTO | H_nSELIN | H_INIT | H_STROBE);
- }
-#endif
ppb_ecp_sync(ppbus);
return (error);
@@ -614,7 +583,7 @@ int
vpoio_attach(struct vpoio_data *vpo)
{
device_t ppbus = device_get_parent(vpo->vpo_dev);
- int epp;
+ int error = 0;
vpo->vpo_nibble_inbyte_msq = (struct ppb_microseq *)malloc(
sizeof(nibble_inbyte_submicroseq), M_DEVBUF, M_NOWAIT);
@@ -631,75 +600,34 @@ vpoio_attach(struct vpoio_data *vpo)
/*
* Initialize mode dependent in/out microsequences
*/
- ppb_request_bus(ppbus, vpo->vpo_dev, PPB_WAIT);
-
- /* enter NIBBLE mode to configure submsq */
- if (ppb_set_mode(ppbus, PPB_NIBBLE) != -1) {
-
- ppb_MS_GET_init(ppbus, vpo->vpo_dev, vpo->vpo_nibble_inbyte_msq);
-
- ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq);
- }
-
- /* enter PS2 mode to configure submsq */
- if (ppb_set_mode(ppbus, PPB_PS2) != -1) {
+ if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_WAIT)))
+ goto error;
+ /* ppbus sets automatically the last mode entered during detection */
+ switch (vpo->vpo_mode_found) {
+ case VP0_MODE_EPP:
+ ppb_MS_GET_init(ppbus, vpo->vpo_dev, epp17_instr_body);
+ ppb_MS_PUT_init(ppbus, vpo->vpo_dev, epp17_outstr_body);
+ printf("vpo%d: EPP mode\n", vpo->vpo_unit);
+ break;
+ case VP0_MODE_PS2:
ppb_MS_GET_init(ppbus, vpo->vpo_dev, ps2_inbyte_submicroseq);
-
ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq);
- }
-
- epp = ppb_get_epp_protocol(ppbus);
-
- /* enter EPP mode to configure submsq */
- if (ppb_set_mode(ppbus, PPB_EPP) != -1) {
-
- switch (epp) {
- case EPP_1_9:
- /* XXX EPP 1.9 support should be improved */
- case EPP_1_7:
- ppb_MS_GET_init(ppbus, vpo->vpo_dev, epp17_instr_body);
-
- ppb_MS_PUT_init(ppbus, vpo->vpo_dev, epp17_outstr_body);
- break;
- default:
- panic("%s: unknown EPP protocol (0x%x)", __FUNCTION__,
- epp);
- }
- }
-
- /* try to enter EPP or PS/2 mode, NIBBLE otherwise */
- if (ppb_set_mode(ppbus, PPB_EPP) != -1) {
- switch (epp) {
- case EPP_1_9:
- printf("vpo%d: EPP 1.9 mode\n", vpo->vpo_unit);
- break;
- case EPP_1_7:
- printf("vpo%d: EPP 1.7 mode\n", vpo->vpo_unit);
- break;
- default:
- panic("%s: unknown EPP protocol (0x%x)", __FUNCTION__,
- epp);
- }
- } else if (ppb_set_mode(ppbus, PPB_PS2) != -1)
printf("vpo%d: PS2 mode\n", vpo->vpo_unit);
-
- else if (ppb_set_mode(ppbus, PPB_NIBBLE) != -1)
+ break;
+ case VP0_MODE_NIBBLE:
+ ppb_MS_GET_init(ppbus, vpo->vpo_dev, vpo->vpo_nibble_inbyte_msq);
+ ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq);
printf("vpo%d: NIBBLE mode\n", vpo->vpo_unit);
-
- else {
- printf("vpo%d: can't enter NIBBLE, PS2 or EPP mode\n",
- vpo->vpo_unit);
-
- ppb_release_bus(ppbus, vpo->vpo_dev);
-
- free(vpo->vpo_nibble_inbyte_msq, M_DEVBUF);
- return (ENXIO);
+ break;
+ default:
+ panic("vpo: unknown mode %d", vpo->vpo_mode_found);
}
ppb_release_bus(ppbus, vpo->vpo_dev);
- return (0);
+error:
+ return (error);
}
/*
diff --git a/sys/dev/ppbus/vpoio.h b/sys/dev/ppbus/vpoio.h
index 211ca00..fe66fa5 100644
--- a/sys/dev/ppbus/vpoio.h
+++ b/sys/dev/ppbus/vpoio.h
@@ -59,8 +59,15 @@ struct vpo_nibble {
char l; /* less significant nibble */
};
+/* Mode found during initialisation */
+#define VP0_MODE_UNDEFINED 0x0
+#define VP0_MODE_NIBBLE 0x1
+#define VP0_MODE_PS2 0x2
+#define VP0_MODE_EPP 0x3
+
struct vpoio_data {
unsigned short int vpo_unit;
+ int vpo_mode_found; /* Mode found during init */
struct vpo_nibble vpo_nibble;
OpenPOWER on IntegriCloud