/* * byte_1284_inbyte() * * Read 1 byte in BYTE mode */ int byte_1284_inbyte(device_t bus, char *buffer) { int error = 0; /* Event 7 - ready to take data (nAUTO low) */ ppb_wctr(bus, (PCD | nINIT | AUTOFEED) & ~(STROBE | SELECTIN)); /* Event 9 - peripheral set nAck low */ if ((error = do_1284_wait(bus, nACK, 0))) { ppb_1284_set_error(bus, PPB_TIMEOUT, 9); goto error; } /* read the byte */ *buffer = ppb_rdtr(bus); /* Event 10 - data received, can't accept more */ ppb_wctr(bus, (nINIT) & ~(AUTOFEED | STROBE | SELECTIN)); /* Event 11 - peripheral ack */ if ((error = do_1284_wait(bus, nACK, nACK))) { ppb_1284_set_error(bus, PPB_TIMEOUT, 11); goto error; } /* Event 16 - strobe */ ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN)); DELAY(3); ppb_wctr(bus, (nINIT) & ~(AUTOFEED | STROBE | SELECTIN)); error: return (error); }
/* * byte_peripheral_outbyte() * * Write 1 byte in BYTE mode */ static int byte_peripheral_outbyte(device_t bus, char *buffer, int last) { int error = 0; /* Event 7 */ if ((error = do_1284_wait(bus, nBUSY, nBUSY))) { ppb_1284_set_error(bus, PPB_TIMEOUT, 7); goto error; } /* check termination */ if (!(ppb_rstr(bus) & SELECT)) { ppb_peripheral_terminate(bus, PPB_WAIT); goto error; } /* Event 15 - put byte on data lines */ #ifdef DEBUG_1284 printf("B"); #endif ppb_wdtr(bus, *buffer); /* Event 9 */ ppb_wctr(bus, (AUTOFEED | STROBE) & ~(nINIT | SELECTIN)); /* Event 10 - wait data read */ if ((error = do_peripheral_wait(bus, nBUSY, 0))) { ppb_1284_set_error(bus, PPB_TIMEOUT, 16); goto error; } /* Event 11 */ if (!last) { ppb_wctr(bus, (AUTOFEED) & ~(nINIT | STROBE | SELECTIN)); } else { ppb_wctr(bus, (nINIT) & ~(STROBE | SELECTIN | AUTOFEED)); } #if 0 /* Event 16 - wait strobe */ if ((error = do_peripheral_wait(bus, nACK | nBUSY, 0))) { ppb_1284_set_error(bus, PPB_TIMEOUT, 16); goto error; } #endif /* check termination */ if (!(ppb_rstr(bus) & SELECT)) { ppb_peripheral_terminate(bus, PPB_WAIT); goto error; } error: return (error); }
static void lpbb_setscl(device_t dev, int val) { device_t ppbus = device_get_parent(dev); ppb_lock(ppbus); if (val == 0) ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) & ~SCL_out)); else ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) | SCL_out)); ppb_unlock(ppbus); }
/* * ppb_1284_terminate() * * IEEE1284 termination phase, return code should ignored since the host * is _always_ in compatible mode after ppb_1284_terminate() */ int ppb_1284_terminate(device_t bus) { #ifdef DEBUG_1284 printf("T"); #endif /* do not reset error here to keep the error that * may occured before the ppb_1284_terminate() call */ ppb_1284_set_state(bus, PPB_TERMINATION); #ifdef PERIPH_1284 /* request remote host attention */ ppb_wctr(bus, (nINIT | STROBE | SELECTIN) & ~(AUTOFEED)); DELAY(1); #endif /* PERIPH_1284 */ /* Event 22 - set nSelectin low and nAutoFeed high */ ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED)); /* Event 24 - waiting for peripheral, Xflag ignored */ if (do_1284_wait(bus, nACK | nBUSY | nFAULT, nFAULT)) { ppb_1284_set_error(bus, PPB_TIMEOUT, 24); goto error; } /* Event 25 - set nAutoFd low */ ppb_wctr(bus, (nINIT | SELECTIN | AUTOFEED) & ~STROBE); /* Event 26 - compatible mode status is set */ /* Event 27 - peripheral set nAck high */ if (do_1284_wait(bus, nACK, nACK)) { ppb_1284_set_error(bus, PPB_TIMEOUT, 27); } /* Event 28 - end termination, return to idle phase */ ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED)); error: /* return to compatible mode */ ppb_set_mode(bus, PPB_COMPATIBLE); ppb_1284_set_state(bus, PPB_FORWARD_IDLE); return (0); }
/* Reset bus by setting SDA first and then SCL. */ static void lpbb_reset_bus(device_t dev) { device_t ppbus = device_get_parent(dev); ppb_assert_locked(ppbus); ppb_wdtr(ppbus, (u_char)~SDA_out); ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) | SCL_out)); }
/* * ppb_peripheral_terminate() * * Terminate peripheral transfer side * * Always return 0 in compatible mode */ int ppb_peripheral_terminate(device_t bus, int how) { int error = 0; #ifdef DEBUG_1284 printf("t"); #endif ppb_1284_set_state(bus, PPB_PERIPHERAL_TERMINATION); /* Event 22 - wait up to host response time (1s) */ if ((error = do_peripheral_wait(bus, SELECT | nBUSY, 0))) { ppb_1284_set_error(bus, PPB_TIMEOUT, 22); goto error; } /* Event 24 */ ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN)); /* Event 25 - wait up to host response time (1s) */ if ((error = do_peripheral_wait(bus, nBUSY, nBUSY))) { ppb_1284_set_error(bus, PPB_TIMEOUT, 25); goto error; } /* Event 26 */ ppb_wctr(bus, (SELECTIN | nINIT | STROBE) & ~(AUTOFEED)); DELAY(1); /* Event 27 */ ppb_wctr(bus, (SELECTIN | nINIT) & ~(STROBE | AUTOFEED)); /* Event 28 - wait up to host response time (1s) */ if ((error = do_peripheral_wait(bus, nBUSY, 0))) { ppb_1284_set_error(bus, PPB_TIMEOUT, 28); goto error; } error: ppb_set_mode(bus, PPB_COMPATIBLE); ppb_1284_set_state(bus, PPB_FORWARD_IDLE); return (0); }
/* * nibble_1284_inbyte() * * Read 1 byte in NIBBLE mode */ int nibble_1284_inbyte(device_t bus, char *buffer) { char nibble[2]; int i, error; for (i = 0; i < 2; i++) { /* Event 7 - ready to take data (nAUTO low) */ ppb_wctr(bus, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN)); /* Event 8 - peripheral writes the first nibble */ /* Event 9 - peripheral set nAck low */ if ((error = do_1284_wait(bus, nACK, 0))) { ppb_1284_set_error(bus, PPB_TIMEOUT, 9); goto error; } /* read nibble */ nibble[i] = ppb_rstr(bus); /* Event 10 - ack, nibble received */ ppb_wctr(bus, nINIT & ~(AUTOFEED | STROBE | SELECTIN)); /* Event 11 - wait ack from peripherial */ if ((error = do_1284_wait(bus, nACK, nACK))) { ppb_1284_set_error(bus, PPB_TIMEOUT, 11); goto error; } } *buffer = ((nibble2char(nibble[1]) << 4) & 0xf0) | (nibble2char(nibble[0]) & 0x0f); error: return (error); }
/* * byte_peripheral_write() * * Write n bytes in BYTE mode */ int byte_peripheral_write(device_t bus, char *buffer, int len, int *sent) { int error = 0, i; char r; ppb_1284_set_state(bus, PPB_PERIPHERAL_TRANSFER); /* wait forever, the remote host is master and should initiate * termination */ for (i=0; i<len; i++) { /* force remote nFAULT low to release the remote waiting * process, if any */ r = ppb_rctr(bus); ppb_wctr(bus, r & ~nINIT); #ifdef DEBUG_1284 printf("y"); #endif /* Event 7 */ error = ppb_poll_bus(bus, PPB_FOREVER, nBUSY, nBUSY, PPB_INTR); if (error && error != EWOULDBLOCK) goto error; #ifdef DEBUG_1284 printf("b"); #endif if ((error = byte_peripheral_outbyte(bus, buffer+i, (i == len-1)))) goto error; } error: if (!error) ppb_1284_set_state(bus, PPB_PERIPHERAL_IDLE); *sent = i; return (error); }
/* * vpoio_do_scsi() * * Send an SCSI command * */ int vpoio_do_scsi(struct vpoio_data *vpo, int host, int target, char *command, int clen, char *buffer, int blen, int *result, int *count, int *ret) { device_t ppbus = device_get_parent(vpo->vpo_dev); register char r; char l, h = 0; int len, error = 0; register int k; /* * enter disk state, allocate the ppbus * * XXX * Should we allow this call to be interruptible? * The only way to report the interruption is to return * EIO do upper SCSI code :^( */ if ((error = vpoio_connect(vpo, PPB_WAIT|PPB_INTR))) return (error); if (!vpoio_in_disk_mode(vpo)) { *ret = VP0_ECONNECT; goto error; } if ((*ret = vpoio_select(vpo,host,target))) goto error; /* * Send the command ... * * set H_SELIN low for vpoio_wait(). */ ppb_wctr(ppbus, H_AUTO | H_nSELIN | H_INIT | H_STROBE); for (k = 0; k < clen; k++) { if (vpoio_wait(vpo, VP0_FAST_SPINTMO) != (char)0xe0) { *ret = VP0_ECMD_TIMEOUT; goto error; } if (vpoio_outstr(vpo, &command[k], 1)) { *ret = VP0_EPPDATA_TIMEOUT; goto error; } } /* * Completion ... */ *count = 0; for (;;) { if (!(r = vpoio_wait(vpo, VP0_LOW_SPINTMO))) { *ret = VP0_ESTATUS_TIMEOUT; goto error; } /* stop when the ZIP wants to send status */ if (r == (char)0xf0) break; if (*count >= blen) { *ret = VP0_EDATA_OVERFLOW; goto error; } /* if in EPP mode or writing bytes, try to transfer a sector * otherwise, just send one byte */ if (PPB_IN_EPP_MODE(ppbus) || r == (char)0xc0) len = (((blen - *count) >= VP0_SECTOR_SIZE)) ? VP0_SECTOR_SIZE : 1; else len = 1; /* ZIP wants to send data? */ if (r == (char)0xc0) error = vpoio_outstr(vpo, &buffer[*count], len); else error = vpoio_instr(vpo, &buffer[*count], len); if (error) { *ret = error; goto error; } *count += len; } if (vpoio_instr(vpo, &l, 1)) { *ret = VP0_EOTHER; goto error; } /* check if the ZIP wants to send more status */ if (vpoio_wait(vpo, VP0_FAST_SPINTMO) == (char)0xf0) if (vpoio_instr(vpo, &h, 1)) { *ret = VP0_EOTHER + 2; goto error; } *result = ((int) h << 8) | ((int) l & 0xff); error: /* return to printer state, release the ppbus */ vpoio_disconnect(vpo); return (0); }
/* * ppb_1284_negociate() * * IEEE1284 negociation phase * * Normal nibble mode or request device id mode (see ppb_1284.h) * * After negociation, nFAULT is low if data is available */ int ppb_1284_negociate(device_t bus, int mode, int options) { int error; int request_mode; #ifdef DEBUG_1284 printf("n"); #endif if (ppb_1284_get_state(bus) >= PPB_PERIPHERAL_NEGOCIATION) ppb_peripheral_terminate(bus, PPB_WAIT); if (ppb_1284_get_state(bus) != PPB_FORWARD_IDLE) ppb_1284_terminate(bus); #ifdef DEBUG_1284 printf("%d", mode); #endif /* ensure the host is in compatible mode */ ppb_set_mode(bus, PPB_COMPATIBLE); /* reset error to catch the actual negociation error */ ppb_1284_reset_error(bus, PPB_FORWARD_IDLE); /* calculate ext. value */ request_mode = ppb_request_mode(mode, options); /* default state */ ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED)); DELAY(1); /* enter negociation phase */ ppb_1284_set_state(bus, PPB_NEGOCIATION); /* Event 0 - put the exten. value on the data lines */ ppb_wdtr(bus, request_mode); #ifdef PERIPH_1284 /* request remote host attention */ ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN)); DELAY(1); ppb_wctr(bus, (nINIT) & ~(STROBE | AUTOFEED | SELECTIN)); #else DELAY(1); #endif /* !PERIPH_1284 */ /* Event 1 - enter IEEE1284 mode */ ppb_wctr(bus, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN)); #ifdef PERIPH_1284 /* ignore the PError line, wait a bit more, remote host's * interrupts don't respond fast enough */ if (ppb_poll_bus(bus, 40, nACK | SELECT | nFAULT, SELECT | nFAULT, PPB_NOINTR | PPB_POLL)) { ppb_1284_set_error(bus, PPB_NOT_IEEE1284, 2); error = ENODEV; goto error; } #else /* Event 2 - trying IEEE1284 dialog */ if (do_1284_wait(bus, nACK | PERROR | SELECT | nFAULT, PERROR | SELECT | nFAULT)) { ppb_1284_set_error(bus, PPB_NOT_IEEE1284, 2); error = ENODEV; goto error; } #endif /* !PERIPH_1284 */ /* Event 3 - latch the ext. value to the peripheral */ ppb_wctr(bus, (nINIT | STROBE | AUTOFEED) & ~SELECTIN); DELAY(1); /* Event 4 - IEEE1284 device recognized */ ppb_wctr(bus, nINIT & ~(SELECTIN | AUTOFEED | STROBE)); /* Event 6 - waiting for status lines */ if (do_1284_wait(bus, nACK, nACK)) { ppb_1284_set_error(bus, PPB_TIMEOUT, 6); error = EBUSY; goto error; } /* Event 7 - quering result consider nACK not to misunderstand * a remote computer terminate sequence */ if (options & PPB_EXTENSIBILITY_LINK) { /* XXX not fully supported yet */ ppb_1284_terminate(bus); return (0); } if (request_mode == NIBBLE_1284_NORMAL) { if (do_1284_wait(bus, nACK | SELECT, nACK)) { ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 7); error = ENODEV; goto error; } } else { if (do_1284_wait(bus, nACK | SELECT, SELECT | nACK)) { ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 7); error = ENODEV; goto error; } } switch (mode) { case PPB_NIBBLE: case PPB_PS2: /* enter reverse idle phase */ ppb_1284_set_state(bus, PPB_REVERSE_IDLE); break; case PPB_ECP: /* negociation ok, now setup the communication */ ppb_1284_set_state(bus, PPB_SETUP); ppb_wctr(bus, (nINIT | AUTOFEED) & ~(SELECTIN | STROBE)); #ifdef PERIPH_1284 /* ignore PError line */ if (do_1284_wait(bus, nACK | SELECT | nBUSY, nACK | SELECT | nBUSY)) { ppb_1284_set_error(bus, PPB_TIMEOUT, 30); error = ENODEV; goto error; } #else if (do_1284_wait(bus, nACK | SELECT | PERROR | nBUSY, nACK | SELECT | PERROR | nBUSY)) { ppb_1284_set_error(bus, PPB_TIMEOUT, 30); error = ENODEV; goto error; } #endif /* !PERIPH_1284 */ /* ok, the host enters the ForwardIdle state */ ppb_1284_set_state(bus, PPB_ECP_FORWARD_IDLE); break; case PPB_EPP: ppb_1284_set_state(bus, PPB_EPP_IDLE); break; default: panic("%s: unknown mode (%d)!", __func__, mode); } ppb_set_mode(bus, mode); return (0); error: ppb_1284_terminate(bus); return (error); }
/* * ppb_peripheral_negociate() * * Negociate the peripheral side */ int ppb_peripheral_negociate(device_t bus, int mode, int options) { int spin, request_mode, error = 0; char r; ppb_set_mode(bus, PPB_COMPATIBLE); ppb_1284_set_state(bus, PPB_PERIPHERAL_NEGOCIATION); /* compute ext. value */ request_mode = ppb_request_mode(mode, options); /* wait host */ spin = 10; while (spin-- && (ppb_rstr(bus) & nBUSY)) DELAY(1); /* check termination */ if (!(ppb_rstr(bus) & SELECT) || !spin) { error = ENODEV; goto error; } /* Event 4 - read ext. value */ r = ppb_rdtr(bus); /* nibble mode is not supported */ if ((r == (char)request_mode) || (r == NIBBLE_1284_NORMAL)) { /* Event 5 - restore direction bit, no data avail */ ppb_wctr(bus, (STROBE | nINIT) & ~(SELECTIN)); DELAY(1); /* Event 6 */ ppb_wctr(bus, (nINIT) & ~(SELECTIN | STROBE)); if (r == NIBBLE_1284_NORMAL) { #ifdef DEBUG_1284 printf("R"); #endif ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 4); error = EINVAL; goto error; } else { ppb_1284_set_state(bus, PPB_PERIPHERAL_IDLE); switch (r) { case BYTE_1284_NORMAL: ppb_set_mode(bus, PPB_BYTE); break; default: break; } #ifdef DEBUG_1284 printf("A"); #endif /* negociation succeeds */ } } else { /* Event 5 - mode not supported */ ppb_wctr(bus, SELECTIN); DELAY(1); /* Event 6 */ ppb_wctr(bus, (SELECTIN) & ~(STROBE | nINIT)); ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 4); #ifdef DEBUG_1284 printf("r"); #endif error = EINVAL; goto error; } return (0); error: ppb_peripheral_terminate(bus, PPB_WAIT); return (error); }