diff options
61 files changed, 63 insertions, 30371 deletions
@@ -4,6 +4,69 @@ `DEVELOPMENT' for details. Partly based on suggestions by Gianluca Guida <glguida@gmail.com>. + * i386/bogus/asc.h: Remove file. + * i386/bogus/aha.h: Likewise. + * i386/bogus/eaha.h: Likewise. + * i386/bogus/sbic.h: Likewise. + * i386/bogus/sci.h: Likewise. + * i386/bogus/sii.h: Likewise. + * i386/bogus/siop.h: Likewise. + * i386/i386at/eisa.h: Likewise. + * scsi/adapters/README: Likewise. + * scsi/adapters/scsi_33C93.h: Likewise. + * scsi/adapters/scsi_33C93_hdw.c: Likewise. + * scsi/adapters/scsi_5380.h: Likewise. + * scsi/adapters/scsi_5380_hdw.c: Likewise. + * scsi/adapters/scsi_53C700.h: Likewise. + * scsi/adapters/scsi_53C700_hdw.c: Likewise. + * scsi/adapters/scsi_53C94.h: Likewise. + * scsi/adapters/scsi_53C94_hdw.c: Likewise. + * scsi/adapters/scsi_7061.h: Likewise. + * scsi/adapters/scsi_7061_hdw.c: Likewise. + * scsi/adapters/scsi_89352.h: Likewise. + * scsi/adapters/scsi_89352_hdw.c: Likewise. + * scsi/adapters/scsi_aha15.h: Likewise. + * scsi/adapters/scsi_aha15_hdw.c: Likewise. + * scsi/adapters/scsi_aha17_hdw.c: Likewise. + * scsi/adapters/scsi_dma.h: Likewise. + * scsi/adapters/scsi_user_dma.c: Likewise. + * scsi/adapters/scsi_user_dma.h: Likewise. + * scsi/compat_30.h: Likewise. + * scsi/disk_label.c: Likewise. + * scsi/mapped_scsi.c: Likewise. + * scsi/mapped_scsi.h: Likewise. + * scsi/pc_scsi_label.c: Likewise. + * scsi/rz.c: Likewise. + * scsi/rz.h: Likewise. + * scsi/rz_audio.c: Likewise. + * scsi/rz_cpu.c: Likewise. + * scsi/rz_disk.c: Likewise. + * scsi/rz_disk_bbr.c: Likewise. + * scsi/rz_host.c: Likewise. + * scsi/rz_labels.h: Likewise. + * scsi/rz_tape.c: Likewise. + * scsi/scsi.c: Likewise. + * scsi/scsi.h: Likewise. + * scsi/scsi2.h: Likewise. + * scsi/scsi_alldevs.c: Likewise. + * scsi/scsi_comm.c: Likewise. + * scsi/scsi_cpu.c: Likewise. + * scsi/scsi_defs.h: Likewise. + * scsi/scsi_disk.c: Likewise. + * scsi/scsi_endian.h: Likewise. + * scsi/scsi_jukebox.c: Likewise. + * scsi/scsi_optical.c: Likewise. + * scsi/scsi_printer.c: Likewise. + * scsi/scsi_rom.c: Likewise. + * scsi/scsi_scanner.c: Likewise. + * scsi/scsi_tape.c: Likewise. + * scsi/scsi_worm.c: Likewise. + * i386/i386at/autoconf.c: Don't include <aha.h> and <eaha.h> anymore + and adopt all users of NAHA and NEAHA as if it were always defined to + `0'. + * i386/i386at/conf.c: Likewise. + * Makefile.in (scsi-files): Remove variable and all users of it. + * i386/bogus/wt.h: Remove file. * i386/i386at/autoconf.c: Don't include <wt.h> anymore and adopt all users of NWT as if it were always defined to `0'. diff --git a/Makefile.in b/Makefile.in index 89c5ad6..bdf4a73 100644 --- a/Makefile.in +++ b/Makefile.in @@ -99,15 +99,6 @@ chips-files = atm.c audio.c bt431.c bt455.c bt459.c build_font.c busses.c \ screen_switch.h serial_defs.h spans.h tca100.h tca100_if.h \ vs42x_rb.h xcfb_monitor.h -# Generic code for various SCSI unit types -scsi-files = disk_label.c mapped_scsi.c pc_scsi_label.c rz.c rz_audio.c \ - rz_cpu.c rz_disk.c rz_disk_bbr.c rz_host.c rz_tape.c scsi.c \ - scsi_alldevs.c scsi_comm.c scsi_cpu.c scsi_disk.c scsi_jukebox.c \ - scsi_optical.c scsi_printer.c scsi_rom.c scsi_scanner.c \ - scsi_tape.c scsi_worm.c \ - compat_30.h mapped_scsi.h rz.h rz_labels.h scsi.h scsi2.h \ - scsi_defs.h scsi_endian.h - # Icky kernel debugger ddb-cfiles = $(addprefix db_,$(ddb-names)) ddb-names = access.c aout.c break.c command.c cond.c examine.c expr.c \ @@ -369,7 +360,6 @@ dist: cp $(addprefix $(srcdir)/device/,$(device-files)) gnumach-$(version)/device cp $(addprefix $(srcdir)/ipc/,$(ipc-files)) gnumach-$(version)/ipc cp $(addprefix $(srcdir)/kern/,$(kern-files)) gnumach-$(version)/kern - cp $(addprefix $(srcdir)/scsi/,$(scsi-files)) gnumach-$(version)/scsi cp $(addprefix $(srcdir)/util/,$(util-files)) gnumach-$(version)/util cp $(addprefix $(srcdir)/vm/,$(vm-files)) gnumach-$(version)/vm cp $(addprefix $(srcdir)/include/,$(mach-headers)) gnumach-$(version)/include/mach diff --git a/i386/bogus/aha.h b/i386/bogus/aha.h deleted file mode 100644 index 370fd1a..0000000 --- a/i386/bogus/aha.h +++ /dev/null @@ -1 +0,0 @@ -#define NAHA 1 diff --git a/i386/bogus/asc.h b/i386/bogus/asc.h deleted file mode 100644 index fcfb5ad..0000000 --- a/i386/bogus/asc.h +++ /dev/null @@ -1 +0,0 @@ -#define NASC 0 diff --git a/i386/bogus/eaha.h b/i386/bogus/eaha.h deleted file mode 100644 index c79f7ad..0000000 --- a/i386/bogus/eaha.h +++ /dev/null @@ -1 +0,0 @@ -#define NEAHA 1 diff --git a/i386/bogus/sbic.h b/i386/bogus/sbic.h deleted file mode 100644 index a0f322c..0000000 --- a/i386/bogus/sbic.h +++ /dev/null @@ -1 +0,0 @@ -#define NSBIC 0 diff --git a/i386/bogus/sci.h b/i386/bogus/sci.h deleted file mode 100644 index 3eb2542..0000000 --- a/i386/bogus/sci.h +++ /dev/null @@ -1 +0,0 @@ -#define NSCI 0 diff --git a/i386/bogus/sii.h b/i386/bogus/sii.h deleted file mode 100644 index 3a914f5..0000000 --- a/i386/bogus/sii.h +++ /dev/null @@ -1 +0,0 @@ -#define NSII 0 diff --git a/i386/bogus/siop.h b/i386/bogus/siop.h deleted file mode 100644 index bffff9d..0000000 --- a/i386/bogus/siop.h +++ /dev/null @@ -1 +0,0 @@ -#define NSIOP 0 diff --git a/i386/i386at/autoconf.c b/i386/i386at/autoconf.c index b8771e8..51f2a0a 100644 --- a/i386/i386at/autoconf.c +++ b/i386/i386at/autoconf.c @@ -47,18 +47,6 @@ #define SPL_TTY (vm_offset_t)SPLTTY -#include <aha.h> -#if NAHA > 0 -extern struct bus_driver aha_driver; -extern int aha_intr(); -#endif /* NAHA */ - -#include <eaha.h> -#if NEAHA > 0 -extern struct bus_driver eaha_driver; -extern int eaha_intr(); -#endif /* NEAHA */ - #include <com.h> #if NCOM > 0 extern struct bus_driver comdriver; @@ -76,74 +64,6 @@ struct bus_ctlr bus_master_init[] = { /* driver name unit intr address len phys_address adaptor alive flags spl pic */ -#ifndef LINUX_DEV -#if NAHA > 0 - {&aha_driver, "ahac", 0, aha_intr, 0x330, 4, 0x330, - '?', 0, 0, SPL_FIVE, 11}, - -#if NAHA > 1 - - {&aha_driver, "ahac", 1, aha_intr, 0x234, 4, 0x234, - '?', 0, 0, SPL_FIVE, 12}, - {&aha_driver, "ahac", 1, aha_intr, 0x230, 4, 0x230, - '?', 0, 0, SPL_FIVE, 12}, - {&aha_driver, "ahac", 1, aha_intr, 0x134, 4, 0x134, - '?', 0, 0, SPL_FIVE, 12}, - {&aha_driver, "ahac", 1, aha_intr, 0x130, 4, 0x130, - '?', 0, 0, SPL_FIVE, 12}, - -#else - - {&aha_driver, "ahac", 0, aha_intr, 0x334, 4, 0x334, - '?', 0, 0, SPL_FIVE, 11}, - {&aha_driver, "ahac", 0, aha_intr, 0x234, 4, 0x234, - '?', 0, 0, SPL_FIVE, 11}, - {&aha_driver, "ahac", 0, aha_intr, 0x230, 4, 0x230, - '?', 0, 0, SPL_FIVE, 11}, - {&aha_driver, "ahac", 0, aha_intr, 0x134, 4, 0x134, - '?', 0, 0, SPL_FIVE, 11}, - {&aha_driver, "ahac", 0, aha_intr, 0x130, 4, 0x130, - '?', 0, 0, SPL_FIVE, 11}, - -#endif /* NAHA > 1 */ -#endif /* NAHA > 0*/ - -#if NEAHA > 0 -{&eaha_driver, "eahac", 0, eaha_intr, 0x0000, 4, 0x0000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0x1000, 4, 0x1000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0x2000, 4, 0x2000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0x3000, 4, 0x3000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0x4000, 4, 0x4000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0x5000, 4, 0x5000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0x6000, 4, 0x6000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0x7000, 4, 0x7000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0x8000, 4, 0x8000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0x9000, 4, 0x9000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0xa000, 4, 0xa000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0xb000, 4, 0xb000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0xc000, 4, 0xc000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0xd000, 4, 0xd000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0xe000, 4, 0xe000, - '?', 0, 0, SPL_FIVE, 12}, -{&eaha_driver, "eahac", 0, eaha_intr, 0xf000, 4, 0xf000, - '?', 0, 0, SPL_FIVE, 12}, -#endif /* NEAHA > 0 */ -#endif /* ! LINUX_DEV */ - 0 }; @@ -153,69 +73,6 @@ struct bus_device bus_device_init[] = { /* driver name unit intr address am phys_address adaptor alive ctlr slave flags *mi *next sysdep sysdep */ -#ifndef LINUX_DEV -#if NAHA > 0 -{ &aha_driver, "rz", 0, 0, 0x0,0, 0, '?', 0, 0, 0, 0, }, -{ &aha_driver, "rz", 1, 0, 0x0,0, 0, '?', 0, 0, 1, 0, }, -{ &aha_driver, "rz", 2, 0, 0x0,0, 0, '?', 0, 0, 2, 0, }, -{ &aha_driver, "rz", 3, 0, 0x0,0, 0, '?', 0, 0, 3, 0, }, -{ &aha_driver, "rz", 4, 0, 0x0,0, 0, '?', 0, 0, 4, 0, }, -{ &aha_driver, "rz", 5, 0, 0x0,0, 0, '?', 0, 0, 5, 0, }, -{ &aha_driver, "rz", 6, 0, 0x0,0, 0, '?', 0, 0, 6, 0, }, -{ &aha_driver, "rz", 7, 0, 0x0,0, 0, '?', 0, 0, 7, 0, }, - -{ &aha_driver, "tz", 0, 0, 0x0,0, 0, '?', 0, 0, 0, 0, }, -{ &aha_driver, "tz", 1, 0, 0x0,0, 0, '?', 0, 0, 1, 0, }, -{ &aha_driver, "tz", 2, 0, 0x0,0, 0, '?', 0, 0, 2, 0, }, -{ &aha_driver, "tz", 3, 0, 0x0,0, 0, '?', 0, 0, 3, 0, }, -{ &aha_driver, "tz", 4, 0, 0x0,0, 0, '?', 0, 0, 4, 0, }, -{ &aha_driver, "tz", 5, 0, 0x0,0, 0, '?', 0, 0, 5, 0, }, -{ &aha_driver, "tz", 6, 0, 0x0,0, 0, '?', 0, 0, 6, 0, }, -{ &aha_driver, "tz", 7, 0, 0x0,0, 0, '?', 0, 0, 7, 0, }, - -#if NAHA > 1 - -{ &aha_driver, "rz", 8, 0, 0x0,0, 0, '?', 0, 1, 0, 0, }, -{ &aha_driver, "rz", 9, 0, 0x0,0, 0, '?', 0, 1, 1, 0, }, -{ &aha_driver, "rz", 10, 0, 0x0,0, 0, '?', 0, 1, 2, 0, }, -{ &aha_driver, "rz", 11, 0, 0x0,0, 0, '?', 0, 1, 3, 0, }, -{ &aha_driver, "rz", 12, 0, 0x0,0, 0, '?', 0, 1, 4, 0, }, -{ &aha_driver, "rz", 13, 0, 0x0,0, 0, '?', 0, 1, 5, 0, }, -{ &aha_driver, "rz", 14, 0, 0x0,0, 0, '?', 0, 1, 6, 0, }, -{ &aha_driver, "rz", 15, 0, 0x0,0, 0, '?', 0, 1, 7, 0, }, - -{ &aha_driver, "tz", 8, 0, 0x0,0, 0, '?', 0, 1, 0, 0, }, -{ &aha_driver, "tz", 9, 0, 0x0,0, 0, '?', 0, 1, 1, 0, }, -{ &aha_driver, "tz", 10, 0, 0x0,0, 0, '?', 0, 1, 2, 0, }, -{ &aha_driver, "tz", 11, 0, 0x0,0, 0, '?', 0, 1, 3, 0, }, -{ &aha_driver, "tz", 12, 0, 0x0,0, 0, '?', 0, 1, 4, 0, }, -{ &aha_driver, "tz", 13, 0, 0x0,0, 0, '?', 0, 1, 5, 0, }, -{ &aha_driver, "tz", 14, 0, 0x0,0, 0, '?', 0, 1, 6, 0, }, -{ &aha_driver, "tz", 15, 0, 0x0,0, 0, '?', 0, 1, 7, 0, }, -#endif /* NAHA > 1 */ -#endif /* NAHA > 0 */ - -#if NEAHA > 0 -{ &eaha_driver, "rz", 0, 0, 0x0,0, 0, '?', 0, 0, 0, 0, }, -{ &eaha_driver, "rz", 1, 0, 0x0,0, 0, '?', 0, 0, 1, 0, }, -{ &eaha_driver, "rz", 2, 0, 0x0,0, 0, '?', 0, 0, 2, 0, }, -{ &eaha_driver, "rz", 3, 0, 0x0,0, 0, '?', 0, 0, 3, 0, }, -{ &eaha_driver, "rz", 4, 0, 0x0,0, 0, '?', 0, 0, 4, 0, }, -{ &eaha_driver, "rz", 5, 0, 0x0,0, 0, '?', 0, 0, 5, 0, }, -{ &eaha_driver, "rz", 6, 0, 0x0,0, 0, '?', 0, 0, 6, 0, }, -{ &eaha_driver, "rz", 7, 0, 0x0,0, 0, '?', 0, 0, 7, 0, }, - -{ &eaha_driver, "tz", 0, 0, 0x0,0, 0, '?', 0, 0, 0, 0, }, -{ &eaha_driver, "tz", 1, 0, 0x0,0, 0, '?', 0, 0, 1, 0, }, -{ &eaha_driver, "tz", 2, 0, 0x0,0, 0, '?', 0, 0, 2, 0, }, -{ &eaha_driver, "tz", 3, 0, 0x0,0, 0, '?', 0, 0, 3, 0, }, -{ &eaha_driver, "tz", 4, 0, 0x0,0, 0, '?', 0, 0, 4, 0, }, -{ &eaha_driver, "tz", 5, 0, 0x0,0, 0, '?', 0, 0, 5, 0, }, -{ &eaha_driver, "tz", 6, 0, 0x0,0, 0, '?', 0, 0, 6, 0, }, -{ &eaha_driver, "tz", 7, 0, 0x0,0, 0, '?', 0, 0, 7, 0, }, -#endif /* NEAHA > 0*/ -#endif /* ! LINUX_DEV */ - #if NCOM > 0 {&comdriver, "com", 0, comintr, 0x3f8, 8, 0x3f8, '?', 0, -1, -1, 0, 0, 0, SPL_TTY, 4}, diff --git a/i386/i386at/conf.c b/i386/i386at/conf.c index a7d420f..2e62ca0 100644 --- a/i386/i386at/conf.c +++ b/i386/i386at/conf.c @@ -36,18 +36,6 @@ extern int timeopen(), timeclose(); extern vm_offset_t timemmap(); #define timename "time" -#include <aha.h> -#if NAHA > 0 -int rz_open(), rz_close(), rz_read(), rz_write(); -int rz_get_status(), rz_set_status(), rz_devinfo(); -int cd_open(), cd_close(), cd_read(), cd_write(); -#define rzname "sd" -#define tzname "st" -#define scname "sc" /* processors */ -#define cdname "cd_audio" /* CD-ROM DA */ - -#endif /*NAHA > 0*/ - #include <par.h> #if NPAR > 0 extern int paropen(), paroutput(), pargetstat(), parsetstat(), @@ -134,29 +122,6 @@ struct dev_ops dev_name_list[] = nodev }, #ifndef LINUX_DEV -#if NAHA > 0 - { rzname, rz_open, rz_close, rz_read, - rz_write, rz_get_status, rz_set_status, nomap, - nodev, nulldev, nulldev, 1024, /* 8 */ - rz_devinfo }, - - { tzname, rz_open, rz_close, rz_read, - rz_write, rz_get_status, rz_set_status, nomap, - nodev, nulldev, nulldev, 8, - nodev }, - - { cdname, cd_open, cd_close, cd_read, - cd_write, nodev, nodev, nomap, - nodev, nulldev, nulldev, 8, - nodev }, - - { scname, rz_open, rz_close, rz_read, - rz_write, rz_get_status, rz_set_status, nomap, - nodev, nulldev, nulldev, 8, - nodev }, - -#endif /*NAHA > 0*/ - #if NPAR > 0 { parname, paropen, nulldev, nulldev, paroutput, pargetstat, parsetstat, nomap, diff --git a/i386/i386at/eisa.h b/i386/i386at/eisa.h deleted file mode 100644 index 33629ca..0000000 --- a/i386/i386at/eisa.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1993 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Copyright 1992 by Open Software Foundation, - * Grenoble, FRANCE - * - * All Rights Reserved - * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby granted, - * provided that the above copyright notice appears in all copies and - * that both the copyright notice and this permission notice appear in - * supporting documentation, and that the name of OSF or Open Software - * Foundation not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. - * - * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, - * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, - * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Eisa defs - */ - -#ifndef _I386AT_EISA_H_ -#define _I386AT_EISA_H_ - -#include <mach/boolean.h> - -#if EISA -extern boolean_t is_eisa_bus; - -#define EISA_ID_REG(board, byte) (0xc80 | (byte) | ((board) << 12)) - -#define EISA_ID_REG_0 0x0 -#define EISA_ID_REG_1 0x1 -#define EISA_ID_REG_2 0x2 -#define EISA_ID_REG_3 0x3 - -#define EISA_SYSTEM_BOARD 0x0 - -struct std_board_id { - unsigned revision: 8, /* Revision number */ - product: 8; /* Product number */ -}; - -struct sys_board_id { - unsigned bus_vers: 3, /* EISA bus version */ - reserved: 13; /* Manufacturer reserved */ -}; - -struct board_id { - union { - struct sys_board_id sys_id; - struct std_board_id std_id; - } bd_id; - unsigned name_char_2: 5, /* 3nd compressed char */ - name_char_1: 5, /* 2nd compressed char */ - name_char_0: 5, /* 1st compressed char */ - not_eisa: 1; /* 0 if eisa board */ -}; - -union eisa_board_id { - unsigned char byte[4]; - struct board_id id; -}; - -typedef union eisa_board_id eisa_board_id_t; - - -/* Additional DMA registers */ - -#define DMA0HIPAGE 0x481 /* DMA 0 address: bits 24-31 */ -#define DMA0HICNT 0x405 /* DMA 0 count: bits 16-23 */ - - -#else /* EISA */ -#define is_eisa_bus FALSE -#define probe_eisa() -#endif /* EISA */ - -#endif /* _I386AT_EISA_H_ */ diff --git a/scsi/adapters/README b/scsi/adapters/README deleted file mode 100644 index 1bc7e7c..0000000 --- a/scsi/adapters/README +++ /dev/null @@ -1,290 +0,0 @@ - -This directory contains various examples of HBA support code, -among them: - - Chip/Board File Machine tested By - - NCR 53C94 scsi_53C94 DecStation 5000 af@cmu - DEC 7061 scsi_7061 DecStation 3100/2100 af@cmu - NCR 5380 scsi_5380 VaxStation 3100 af@cmu - Fujitsu 89352 scsi_89352 Omron Luna88k danner@cmu - Adaptec 1542B scsi_aha15 AT/PC af@cmu - -It should be trivial to modify them for some other machine that uses -the same SCSI chips, hopefully by properly conditionalizing and macroizing -the existing code. - -There are various rules and assumptions to keep in mind when designing/coding -the support code for a new HBA, here is a list. Pls extend this with -anything you find is not openly stated here and made your life miserable -during the port, and send it back to CMU. - - -AUTOCONF - -We assume the structures and procedures defined in chips/busses.*, -e.g. someone will call configure_bus_master to get to our foo_probe() -routine. This should make up its mind on how many targets it sees -[see later for dynamic reconfig], allocate a descriptor for each -one and leave the driver ready to accept commands (via foo_go()). - - On raw chips you should use a test_unit_ready command, - selecting without ATN, and timing out on non-existant - devices. Use LUN 0. - On boards, there probably is a command to let the board do - it (see Adaptec), if not do as above. - -The typical autoconf descriptor might look like - - caddr_t foo_std[NFOO] = { 0 }; - struct bus_device *foo_dinfo[NFOO*8]; - struct bus_ctlr *foo_minfo[NFOO]; - struct bus_driver foo_driver = - { foo_probe, scsi_slave, scsi_attach, foo_go, foo_std, "rz", - foo_dinfo, "foo", foo_minfo, BUS_INTR_B4_PROBE}; - -which indicates that foo_probe() and foo_go() are our interface functions, -and we use the generic scsi_slave() and scsi_attach() for the rest. -Their definition is - - foo_probe(reg, ui) - vm_offset_t reg; - struct bus_ctlr *ui; - -[the "reg" argument might actually be something else on architectures that - do not use memory mapped I/O] - - aha_go(tgt, cmd_count, in_count, cmd_only) - target_info_t *tgt; - boolean_t cmd_only; - -The foo_go() routine is fairly common across chips, look at any example to -see how to structure it. Basically, the arguments tell us how much data -to expect in either direction, and whether (cmd_only) we think we should -be selecting with ATN (cmd_only==FALSE) or not. The only gotcha is cmd_count -actually includes the size of any parameters. - -The "go" field of the scsi_softc structure describing your HBA should be -set to your foo_go() routine, by the foo_probe() routine. - -DATA DEPENDENCIES - -The upper layer assumes that tgt->cmd_ptr is a pointer to good memory -[e.g. no funny padding] where it places the scsi command control blocks -AND small (less than 255 bytes) parameters. It also expects small results -in there (things like read_capacity, for instance). I think I cleaned -up all the places that used to assume tgt->cmd_ptr was aligned, but do not -be surprised if I missed one. - -It does NOT use the dma_ptr, or any of the transient_state fields. - -WATCHDOG - -There is an optional MI watchdog facility, which can be used quite simply by -filling in the "watchdog" field of the scsi_softc structure describing -your HBA. To disable it, leave the field zero (or, dynamically, zero the -timeout value). You can use a watchdog of your own if you like, or more -likely set this field to point to the MI scsi_watchdog(). -This requires that your foo_softc descriptor starts off with a watchdog_t -structure, with the "reset" field pointing to a function that will -reset the SCSI bus should the watchdog expire. - -When a new SCSI command is initiated you should - if (foo->wd.nactive++ == 0) - foo->wd.watchdog_state = SCSI_WD_ACTIVE; -to activate the watchdog, on each interrupt [or other signal that all -is proceeding well for the command and it is making progress] you should - if (foo->wd.nactive) - foo->wd.watchdog_state = SCSI_WD_ACTIVE; -bump down the watchdog 'trigger level', and when the command terminates - if (aha->wd.nactive-- == 1) - aha->wd.watchdog_state = SCSI_WD_INACTIVE; - -When you detect a SCSI bus reset (possibly we initiated it) you should - aha->wd.nactive = 0; -and after cleaning up properly invoke - scsi_bus_was_reset(sc) - scsi_softc_t sc; - -The functiona that is invoked on watchdog expiry is - foo_reset_scsibus(foo) - register foo_softc_t foo; - -Note that this can be used for dumb chips that do not support select timeouts -in hardware [see the 5380 or 7061 code], but its primary use is to detect -instances where a target is holding on the SCSI bus way too long. - -The one drawback of resetting the bus is that some devices (like tapes) -lose status in case of a reset, and the MI code does not (yet?) try to -keep enough information around to be able to recover. If you want to -add something very useful you might change the rz_tape.c code to do just -that, e.g. on SCSI_RET_ABORTs wait a while for the tape to do whatever, -then rewind, and seek forward where the tape should have been positioned at -the beginning of the command that failed, then reissue the command. -None of the examples so far tries to be 'smart' like making an attempt -to get the bus unstuck without resetting it, send us ideas if you have -some. - - -DYNAMIC RECONFIG - -Your code should be ready to add/remove targets on the fly. To do so, -notify the upper layer that a target went offline returning -SCSI_RET_DEVICE_DOWN when e.g. the select timed out, and clear out -the tgt->flags field. -To find new devices, define a function - - boolean_t - foo_probe_target(tgt, ior) - target_info_t *tgt; - io_req_t ior; - -and install it in the "probe" field of the scsi_softc_t structure describing -the HBA to the upper layer. This function should finalize all HBA-specific -info in the target_info structure, then do a scsi_inquiry and check the -return code. If this is not SCSI_RET_DEVICE_DOWN the target should be -marked TGT_ALIVE. - - -COMMAND TERMINATION - -Generally, command termination should be reported to the upper layers -by setting the tgt->done field to the proper value [it should remain -SCSI_RET_IN_PROGRESS while the command is executing] and invoking the -target's completion routine, like: - if (tgt->ior) { - LOG(0xA,"ops->restart"); - (*tgt->dev_ops->restart)( tgt, TRUE); - } -Note that early on some commands will actually wait for completion -by spinning on the tgt->done value, because autoconf happens when -threads and the scheduler are not working. - -Return SCSI_RET_RETRY if the target was busy, the command will be retried -as appropriate. - -Check the completion routines [in rz_disk.c and rz_tape.c for instance] -if you are not sure what to return in a troubled case. - -HBA CHIPS GOTCHAS - -All of the examples so far use the idea of 'scripts': the interrupt routine -matches the chip state with what is expected and if this is ok (it is -in the common important case) it just calls a prepackaged function. -We have found this to be _extremely_ simpler than using a state machine -of various ridiculous and erroneous sorts, and much more handy for debugging -also. Not to mention the saving on code. -Nonetheless, there really are no restrictions on how to structure the HBA -code, if you prefer state machines go ahead and use them! - -Scheduling of the bus among competing targets is one of the major missing -pieces for simple HBAs. A winning strategy used so far is as follows. -Allocate a queue_head_t of waiting_targets in your foo_softc, and two -target_info_t pointers next_target and active_target. A three-valued -state field is also needed. If you enter the foo_go() routine -and find the state&BUSY simply enqueue_tail() your tgt on the waiting_targets -queue. Otherwise mark the bus BUSY, set next_target to tgt, and proceed -to a selection attempt. -Note that the attempt might fail and a reselection win over it, therefore -the attempt_selection() routine should just retrieve the next_target -and install it in active_target, start the selection and let the interrupt -routine take care of the rest [see scsi_5380 for a different setup]. -If a reselection wins we should note that we had a COLLISION in the state -field, install the reconecting target and proceed to completion. -When either a command is complete or a target disconnects you should invoke -a foo_release_bus() routine, which might look like: - -boolean_t -foo_release_bus(foo) - register foo_softc_t foo; -{ - boolean_t ret = TRUE; - - LOG(9,"release"); - if (foo->state & FOO_STATE_COLLISION) { - - LOG(0xB,"collided"); - foo->state &= ~FOO_STATE_COLLISION; - foo_attempt_selection(foo); - - } else if (queue_empty(&foo->waiting_targets)) { - - foo->state &= ~FOO_STATE_BUSY; - foo->active_target = 0; - foo->script = 0; - ret = FALSE; - - } else { - - LOG(0xC,"dequeue"); - foo->next_target = (target_info_t *) - dequeue_head(&foo->waiting_targets); - foo_attempt_selection(foo); - } - return ret; -} - -which indicates whether the bus has been handed off to a new target or not. -This provides the desired FIFO scheduling of the bus and gives maximum -parallelism when targets are allowed to (and infact do) disconnect. - -An area where there are problems most times is how to minimize the -interaction of selections and reselections in, e.g. foo_attempt_selection(). -This is very much chip specific, but sneaking on the SCSI bus should -be a viable alternative in most cases. Check in the specs what happens -if you send a command while there is already a reselection pending: -a well behaved chip would ignore the command and not screwup its status. -[Keep in mind that even if _now_ there is no reselection indication - on the next cycle there might be and you won't see it!] - -RANDOM GOTCHAS - -A number of workstations do not provide real DMA support [do not ask me why] -but rather a special 'buffer' more or less wide where you have to copy -data to and from. This has been handled, see esp the 52C94 code which has -even the extreme optimization of issuing the send command even before -the data has been copied into the buffer! We have handled even machines -where no DMA at all was provided. - -Speaking of DMA.. many of these chips 'prefetch' data, or have a FIFO -on board (they have to if they do synch xfers), and when the target -disconnects it is always a pain to find out how many bytes exactly did we -xfer. Be advised that this hurdle exists, and that the best way to -debug your code here is to use a tape. A safe way is to initially -disable disconnects [so that you can get the system up from disk] -and enable them only on the tape unit that you are using for testing. -Later on enable disks but make sure you have some way to recover from -a zapped disk ! - -MOVING TO USER SPACE - -All examples have hooks for user-space versions of the driver, the -ones for 54C94 and 7061 actually do work. Look in mapped_scsi.c -for how this is done, it is fairly simple as far as the kernel is -concerned. To keep the option of mapping to user space open you -should structure your interrupt routine such that it does all the -state gathering and clearing of the interrupt right away. This -scheme gives you some assurance that your code will keep on working -when the interrupt processing is actually delayed and you recover -the interrupt state from the saved structure in the mapped area. - - -IMPROVEMENTS - -There are a variety of things to be done still, for instance: - -- rewrite scsi_slave() and scsi_attach() to be fully SCSI-II compliant. - There are only comments right now as to how that should be done. - -- add enough machinery to the tape code to be able to recover from - bus resets. Do so in such a way that other devices might use the ideas. - -- add more devices, like printers scanners modems etc that are currently - missing - -- add a 'generic' set_status flavor which simply executes a scsi command - passed in from user. This seems the way many vendors and other people - have strutured their drivers, it would make it possible to have a common - user-level program to do special maintainance work like, for instance, - reformatting of disks. - diff --git a/scsi/adapters/scsi_33C93.h b/scsi/adapters/scsi_33C93.h deleted file mode 100644 index 454a8eb..0000000 --- a/scsi/adapters/scsi_33C93.h +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_33C93.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 8/91 - * - * Defines for the WD/AMD 33C93 SBIC (SCSI Bus Interface Controller) - */ - -/* - * Register map, w mux addressing - */ - -typedef struct { - - volatile unsigned char sbic_myid; /* rw: My SCSI id */ -#define sbic_cdbsize sbic_myid /* w : size of CDB */ - - volatile unsigned char sbic_control; /* rw: Control register */ - - volatile unsigned char sbic_timeo; /* rw: Timeout period */ - - volatile unsigned char sbic_cdb1; /* rw: CDB, 1st byte */ -#define sbic_tsecs sbic_cdb1 /* rw: Xlate: nsectors */ - - volatile unsigned char sbic_cdb2; /* rw: CDB, 2nd byte */ -#define sbic_theads sbic_cdb2 /* rw: Xlate: nheads */ - - volatile unsigned char sbic_cdb3; /* rw: CDB, 3rd byte */ -#define sbic_tcyl_hi sbic_cdb3 /* rw: Xlate: ncyls, hi */ - - volatile unsigned char sbic_cdb4; /* rw: CDB, 4th byte */ -#define sbic_tcyl_lo sbic_cdb4 /* rw: Xlate: ncyls, lo */ - - volatile unsigned char sbic_cdb5; /* rw: CDB, 5th byte */ -#define sbic_addr_hi sbic_cdb5 /* rw: Xlate: address, hi */ - - volatile unsigned char sbic_cdb6; /* rw: CDB, 6th byte */ -#define sbic_addr_2 sbic_cdb6 /* rw: Xlate: address */ - - volatile unsigned char sbic_cdb7; /* rw: CDB, 7th byte */ -#define sbic_addr_3 sbic_cdb7 /* rw: Xlate: address */ - - volatile unsigned char sbic_cdb8; /* rw: CDB, 8th byte */ -#define sbic_addr_lo sbic_cdb8 /* rw: Xlate: address, lo */ - - volatile unsigned char sbic_cdb9; /* rw: CDB, 9th byte */ -#define sbic_secno sbic_cdb9 /* rw: Xlate: sector no */ - - volatile unsigned char sbic_cdb10; /* rw: CDB, 10th byte */ -#define sbic_headno sbic_cdb10 /* rw: Xlate: head no */ - - volatile unsigned char sbic_cdb11; /* rw: CDB, 11th byte */ -#define sbic_cylno_hi sbic_cdb11/* rw: Xlate: cyl no, hi */ - - volatile unsigned char sbic_cdb12; /* rw: CDB, 12th byte */ -#define sbic_cylno_lo sbic_cdb12/* rw: Xlate: cyl no, lo */ - - volatile unsigned char sbic_tlun; /* rw: Target LUN */ - - volatile unsigned char sbic_cmd_phase; /* rw: Command phase */ - - volatile unsigned char sbic_syn; /* rw: Synch xfer params */ - - volatile unsigned char sbic_count_hi; /* rw: Xfer count, hi */ - - volatile unsigned char sbic_count_med; /* rw: Xfer count, med */ - - volatile unsigned char sbic_count_lo; /* rw: Xfer count, lo */ - - volatile unsigned char sbic_selid; /* rw: Target ID (select) */ - - volatile unsigned char sbic_rselid; /* rw: Target ID (reselect) */ - - volatile unsigned char sbic_csr; /* r : Status register */ - - volatile unsigned char sbic_cmd; /* rw: Command register */ - - volatile unsigned char sbic_data; /* rw: FIFO top */ - - char u0; /* unused, padding */ - char u1; /* unused, padding */ - char u2; /* unused, padding */ - char u3; /* unused, padding */ - char u4; /* unused, padding */ - - volatile unsigned char sbic_asr; /* r : Aux Status Register */ - -} sbic_mux_regmap_t; - -/* - * Register map, non mux (indirect) addressing - */ -typedef struct { - volatile unsigned char sbic_asr; /* r : Aux Status Register */ -#define sbic_address sbic_asr /* w : desired register no */ - - volatile unsigned char sbic_value; /* rw: register value */ -} sbic_ind_regmap_t; - -#define sbic_read_reg(regs,regno,val) { \ - (regs)->sbic_address = (regno); \ - wbflush(); \ - (val) = (regs)->sbic_value; \ - } - -#define sbic_write_reg(regs,regno,val) { \ - (regs)->sbic_address = (regno); \ - wbflush(); \ - (regs)->sbic_value = (val); \ - } - -#define SBIC_myid 0 -#define SBIC_cdbsize 0 -#define SBIC_control 1 -#define SBIC_timeo 2 -#define SBIC_cdb1 3 -#define SBIC_tsecs 3 -#define SBIC_cdb2 4 -#define SBIC_theads 4 -#define SBIC_cdb3 5 -#define SBIC_tcyl_hi 5 -#define SBIC_cdb4 6 -#define SBIC_tcyl_lo 6 -#define SBIC_cdb5 7 -#define SBIC_addr_hi 7 -#define SBIC_cdb6 8 -#define SBIC_addr_2 8 -#define SBIC_cdb7 9 -#define SBIC_addr_3 9 -#define SBIC_cdb8 10 -#define SBIC_addr_lo 10 -#define SBIC_cdb9 11 -#define SBIC_secno 11 -#define SBIC_cdb10 12 -#define SBIC_headno 12 -#define SBIC_cdb11 13 -#define SBIC_cylno_hi 13 -#define SBIC_cdb12 14 -#define SBIC_cylno_lo 14 -#define SBIC_tlun 15 -#define SBIC_cmd_phase 16 -#define SBIC_syn 17 -#define SBIC_count_hi 18 -#define SBIC_count_med 19 -#define SBIC_count_lo 20 -#define SBIC_selid 21 -#define SBIC_rselid 22 -#define SBIC_csr 23 -#define SBIC_cmd 24 -#define SBIC_data 25 -/* sbic_asr is addressed directly */ - -/* - * Register defines - */ - -/* - * Auxiliary Status Register - */ - -#define SBIC_ASR_INT 0x80 /* Interrupt pending */ -#define SBIC_ASR_LCI 0x40 /* Last command ignored */ -#define SBIC_ASR_BSY 0x20 /* Busy, only cmd/data/asr readable */ -#define SBIC_ASR_CIP 0x10 /* Busy, cmd unavail also */ -#define SBIC_ASR_xxx 0x0c -#define SBIC_ASR_PE 0x02 /* Parity error (even) */ -#define SBIC_ASR_DBR 0x01 /* Data Buffer Ready */ - -/* - * My ID register, and/or CDB Size - */ - -#define SBIC_ID_FS_8_10 0x00 /* Input clock is 8-10 Mhz */ - /* 11 Mhz is invalid */ -#define SBIC_ID_FS_12_15 0x40 /* Input clock is 12-15 Mhz */ -#define SBIC_ID_FS_16_20 0x80 /* Input clock is 16-20 Mhz */ -#define SBIC_ID_EHP 0x10 /* Enable host parity */ -#define SBIC_ID_EAF 0x08 /* Enable Advanced Features */ -#define SBIC_ID_MASK 0x07 -#define SBIC_ID_CBDSIZE_MASK 0x0f /* if unk SCSI cmd group */ - -/* - * Control register - */ - -#define SBIC_CTL_DMA 0x80 /* Single byte dma */ -#define SBIC_CTL_DBA_DMA 0x40 /* direct buffer acces (bus master)*/ -#define SBIC_CTL_BURST_DMA 0x20 /* continuous mode (8237) */ -#define SBIC_CTL_NO_DMA 0x00 /* Programmed I/O */ -#define SBIC_CTL_HHP 0x10 /* Halt on host parity error */ -#define SBIC_CTL_EDI 0x08 /* Ending disconnect interrupt */ -#define SBIC_CTL_IDI 0x04 /* Intermediate disconnect interrupt*/ -#define SBIC_CTL_HA 0x02 /* Halt on ATN */ -#define SBIC_CTL_HSP 0x01 /* Halt on SCSI parity error */ - -/* - * Timeout period register - * [val in msecs, input clk in Mhz] - */ - -#define SBIC_TIMEOUT(val,clk) ((((val)*(clk))/80)+1) - -/* - * CDBn registers, note that - * cdb11 is used for status byte in target mode (send-status-and-cc) - * cdb12 sez if linked command complete, and w/flag if so - */ - -/* - * Target LUN register - * [holds target status when select-and-xfer] - */ - -#define SBIC_TLUN_VALID 0x80 /* did we receive an Identify msg */ -#define SBIC_TLUN_DOK 0x40 /* Disconnect OK */ -#define SBIC_TLUN_xxx 0x38 -#define SBIC_TLUN_MASK 0x07 - -/* - * Command Phase register - */ - -#define SBIC_CPH_MASK 0x7f /* values/restarts are cmd specific */ -#define SBIC_CPH(p) ((p)&SBIC_CPH_MASK) - -/* - * FIFO register - */ - -#define SBIC_FIFO_DEEP 12 - -/* - * Synchronous xfer register - */ - -#define SBIC_SYN_OFF_MASK 0x0f -#define SBIC_SYN_MAX_OFFSET (SBIC_FIFO_DEEP-1) -#define SBIC_SYN_PER_MASK 0x70 -#define SBIC_SYN_MIN_PERIOD 2 /* upto 8, encoded as 0 */ - -#define SBIC_SYN(o,p) (((o)&SBIC_SYN_OFF_MASK)|(((p)<<4)&SBIC_SYN_PER_MASK)) - -/* - * Transfer count register - * optimal access macros depend on addressing - */ - -/* - * Destination ID (selid) register - */ - -#define SBIC_SID_SCC 0x80 /* Select command chaining (tgt) */ -#define SBIC_SID_DPD 0x40 /* Data phase direction (inittor) */ -# define SBIC_SID_FROM_SCSI 0x40 -# define SBIC_SID_TO_SCSI 0x00 -#define SBIC_SID_xxx 0x38 -#define SBIC_SID_IDMASK 0x07 - -/* - * Source ID (rselid) register - */ - -#define SBIC_RID_ER 0x80 /* Enable reselection */ -#define SBIC_RID_ES 0x40 /* Enable selection */ -#define SBIC_RID_DSP 0x20 /* Disable select parity */ -#define SBIC_RID_SIV 0x08 /* Source ID valid */ -#define SBIC_RID_MASK 0x07 - -/* - * Status register - */ - -#define SBIC_CSR_CAUSE 0xf0 -# define SBIC_CSR_RESET 0x00 /* chip was reset */ -# define SBIC_CSR_CMD_DONE 0x10 /* cmd completed */ -# define SBIC_CSR_CMD_STOPPED 0x20 /* interrupted or abrted*/ -# define SBIC_CSR_CMD_ERR 0x40 /* end with error */ -# define SBIC_CSR_BUS_SERVICE 0x80 /* REQ pending on the bus */ - -#define SBIC_CSR_QUALIFIER 0x0f - - /* Reset State Interrupts */ -# define SBIC_CSR_RESET 0x00 /* reset w/advanced features*/ -# define SBIC_CSR_RESET_AM 0x01 /* reset w/advanced features*/ - - /* Successful Completion Interrupts */ -# define SBIC_CSR_TARGET 0x10 /* reselect complete */ -# define SBIC_CSR_INITIATOR 0x11 /* select complete */ -# define SBIC_CSR_WO_ATN 0x13 /* tgt mode completion */ -# define SBIC_CSR_W_ATN 0x14 /* ditto */ -# define SBIC_CSR_XLATED 0x15 /* translate address cmd */ -# define SBIC_CSR_S_XFERRED 0x16 /* initiator mode completion*/ -# define SBIC_CSR_XFERRED 0x18 /* phase in low bits */ - - /* Paused or Aborted Interrupts */ -# define SBIC_CSR_MSGIN_W_ACK 0x20 /* (I) msgin, ACK asserted*/ -# define SBIC_CSR_SDP 0x21 /* (I) SDP msg received */ -# define SBIC_CSR_SEL_ABRT 0x22 /* sel/resel aborted */ -# define SBIC_CSR_XFR_PAUSED 0x23 /* (T) no ATN */ -# define SBIC_CSR_XFR_PAUSED_ATN 0x24 /* (T) ATN is asserted */ -# define SBIC_CSR_RSLT_AM 0x27 /* (I) lost selection (AM) */ -# define SBIC_CSR_MIS 0x28 /* (I) xfer aborted, ph mis */ - - /* Terminated Interrupts */ -# define SBIC_CSR_CMD_INVALID 0x40 -# define SBIC_CSR_DISC 0x41 /* (I) tgt disconnected */ -# define SBIC_CSR_SEL_TIMEO 0x42 -# define SBIC_CSR_PE 0x43 /* parity error */ -# define SBIC_CSR_PE_ATN 0x44 /* ditto, ATN is asserted */ -# define SBIC_CSR_XLATE_TOOBIG 0x45 -# define SBIC_CSR_RSLT_NOAM 0x46 /* (I) lost sel, no AM mode */ -# define SBIC_CSR_BAD_STATUS 0x47 /* status byte was nok */ -# define SBIC_CSR_MIS_1 0x48 /* ph mis, see low bits */ - - /* Service Required Interrupts */ -# define SBIC_CSR_RSLT_NI 0x80 /* reselected, no ify msg */ -# define SBIC_CSR_RSLT_IFY 0x81 /* ditto, AM mode, got ify */ -# define SBIC_CSR_SLT 0x82 /* selected, no ATN */ -# define SBIC_CSR_SLT_ATN 0x83 /* selected with ATN */ -# define SBIC_CSR_ATN 0x84 /* (T) ATN asserted */ -# define SBIC_CSR_DISC_1 0x85 /* (I) bus is free */ -# define SBIC_CSR_UNK_GROUP 0x87 /* strange CDB1 */ -# define SBIC_CSR_MIS_2 0x88 /* (I) ph mis, see low bits */ - -#define SBIC_PHASE(csr) SCSI_PHASE(csr) - -/* - * Command register (command codes) - */ - -#define SBIC_CMD_SBT 0x80 /* Single byte xfer qualifier */ -#define SBIC_CMD_MASK 0x7f - - /* Miscellaneous */ -#define SBIC_CMD_RESET 0x00 /* (DTI) lev I */ -#define SBIC_CMD_ABORT 0x01 /* (DTI) lev I */ -#define SBIC_CMD_DISC 0x04 /* ( TI) lev I */ -#define SBIC_CMD_SSCC 0x0d /* ( TI) lev I */ -#define SBIC_CMD_SET_IDI 0x0f /* (DTI) lev I */ -#define SBIC_CMD_XLATE 0x18 /* (DT ) lev II */ - - /* Initiator state */ -#define SBIC_CMD_SET_ATN 0x02 /* ( I) lev I */ -#define SBIC_CMD_CLR_ACK 0x03 /* ( I) lev I */ -#define SBIC_CMD_XFER_INFO 0x20 /* ( I) lev II */ - - /* Target state */ -#define SBIC_CMD_SND_DISC 0x0e /* ( T ) lev II */ -#define SBIC_CMD_RCV_CMD 0x10 /* ( T ) lev II */ -#define SBIC_CMD_RCV_DATA 0x11 /* ( T ) lev II */ -#define SBIC_CMD_RCV_MSG_OUT 0x12 /* ( T ) lev II */ -#define SBIC_CMD_RCV 0x13 /* ( T ) lev II */ -#define SBIC_CMD_SND_STATUS 0x14 /* ( T ) lev II */ -#define SBIC_CMD_SND_DATA 0x15 /* ( T ) lev II */ -#define SBIC_CMD_SND_MSG_IN 0x16 /* ( T ) lev II */ -#define SBIC_CMD_SND 0x17 /* ( T ) lev II */ - - /* Disconnected state */ -#define SBIC_CMD_RESELECT 0x05 /* (D ) lev II */ -#define SBIC_CMD_SEL_ATN 0x06 /* (D ) lev II */ -#define SBIC_CMD_SEL 0x07 /* (D ) lev II */ -#define SBIC_CMD_SEL_ATN_XFER 0x08 /* (D I) lev II */ -#define SBIC_CMD_SEL_XFER 0x09 /* (D I) lev II */ -#define SBIC_CMD_RESELECT_RECV 0x0a /* (DT ) lev II */ -#define SBIC_CMD_RESELECT_SEND 0x0b /* (DT ) lev II */ -#define SBIC_CMD_WAIT_SEL_RECV 0x0c /* (DT ) lev II */ - - -/* approximate, but we won't do SBT on selects */ -#define sbic_isa_select(cmd) (((cmd)>0x5)&&((cmd)<0xa)) - diff --git a/scsi/adapters/scsi_33C93_hdw.c b/scsi/adapters/scsi_33C93_hdw.c deleted file mode 100644 index 169ccbf..0000000 --- a/scsi/adapters/scsi_33C93_hdw.c +++ /dev/null @@ -1,2078 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS AS-IS - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_33C93_hdw.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 8/91 - * - * Bottom layer of the SCSI driver: chip-dependent functions - * - * This file contains the code that is specific to the WD/AMD 33C93 - * SCSI chip (Host Bus Adapter in SCSI parlance): probing, start - * operation, and interrupt routine. - */ - -#if 0 -DISCLAIMER: THIS DOES NOT EVEN COMPILE YET, it went in by mistake. -Code that probably makes some sense is from here to "TILL HERE" - -/* - * This layer works based on small simple 'scripts' that are installed - * at the start of the command and drive the chip to completion. - * The idea comes from the specs of the NCR 53C700 'script' processor. - * - * There are various reasons for this, mainly - * - Performance: identify the common (successful) path, and follow it; - * at interrupt time no code is needed to find the current status - * - Code size: it should be easy to compact common operations - * - Adaptability: the code skeleton should adapt to different chips without - * terrible complications. - * - Error handling: and it is easy to modify the actions performed - * by the scripts to cope with strange but well identified sequences - * - */ - -#include <sbic.h> -#if NSBIC > 0 -#include <platforms.h> - -#ifdef IRIS -#define PAD(n) char n[3] /* or whatever */ -#define SBIC_MUX_ADDRESSING /* comment out if wrong */ -#define SBIC_CLOCK_FREQUENCY 20 /* FIXME FIXME FIXME */ -#define SBIC_MACHINE_DMA_MODE SBIC_CTL_DMA /* FIXME FIXME FIXME */ - -#define SBIC_SET_RST_ADDR /*SCSI_INIT_ADDR*/ -#define SBIC_CLR_RST_ADDR /*SCSI_RDY_ADDR*/ -#define SBIC_MACHINE_RESET_SCSIBUS(regs,per) \ - { int temp; \ - temp = *(volatile unsigned int *)SBIC_SET_RST_ADDR; \ - delay(per); \ - temp = *(volatile unsigned int *)SBIC_CLR_RST_ADDR; \ - } - -#endif - -#include <machine/machspl.h> /* spl definitions */ -#include <mach/std_types.h> -#include <sys/types.h> -#include <chips/busses.h> -#include <scsi/compat_30.h> - -#include <scsi/scsi.h> -#include <scsi/scsi2.h> - -#include <scsi/adapters/scsi_33C93.h> -#include <scsi/scsi_defs.h> -#include <scsi/adapters/scsi_dma.h> - -/* - * Spell out all combinations of padded/nopadded and mux/nomux - */ -#ifdef PAD -typedef struct { - - volatile unsigned char sbic_myid; /* rw: My SCSI id */ -/*#define sbic_cdbsize sbic_myid /* w : size of CDB */ - PAD(pad0) - volatile unsigned char sbic_control; /* rw: Control register */ - PAD(pad1) - volatile unsigned char sbic_timeo; /* rw: Timeout period */ - PAD(pad2) - volatile unsigned char sbic_cdb1; /* rw: CDB, 1st byte */ - PAD(pad3) - volatile unsigned char sbic_cdb2; /* rw: CDB, 2nd byte */ - PAD(pad4) - volatile unsigned char sbic_cdb3; /* rw: CDB, 3rd byte */ - PAD(pad5) - volatile unsigned char sbic_cdb4; /* rw: CDB, 4th byte */ - PAD(pad6) - volatile unsigned char sbic_cdb5; /* rw: CDB, 5th byte */ - PAD(pad7) - volatile unsigned char sbic_cdb6; /* rw: CDB, 6th byte */ - PAD(pad8) - volatile unsigned char sbic_cdb7; /* rw: CDB, 7th byte */ - PAD(pad9) - volatile unsigned char sbic_cdb8; /* rw: CDB, 8th byte */ - PAD(pad10) - volatile unsigned char sbic_cdb9; /* rw: CDB, 9th byte */ - PAD(pad11) - volatile unsigned char sbic_cdb10; /* rw: CDB, 10th byte */ - PAD(pad12) - volatile unsigned char sbic_cdb11; /* rw: CDB, 11th byte */ - PAD(pad13) - volatile unsigned char sbic_cdb12; /* rw: CDB, 12th byte */ - PAD(pad14) - volatile unsigned char sbic_tlun; /* rw: Target LUN */ - PAD(pad15) - volatile unsigned char sbic_cmd_phase; /* rw: Command phase */ - PAD(pad16) - volatile unsigned char sbic_syn; /* rw: Synch xfer params */ - PAD(pad17) - volatile unsigned char sbic_count_hi; /* rw: Xfer count, hi */ - PAD(pad18) - volatile unsigned char sbic_count_med; /* rw: Xfer count, med */ - PAD(pad19) - volatile unsigned char sbic_count_lo; /* rw: Xfer count, lo */ - PAD(pad20) - volatile unsigned char sbic_selid; /* rw: Target ID (select) */ - PAD(pad21) - volatile unsigned char sbic_rselid; /* rw: Target ID (reselect) */ - PAD(pad22) - volatile unsigned char sbic_csr; /* r : Status register */ - PAD(pad23) - volatile unsigned char sbic_cmd; /* rw: Command register */ - PAD(pad24) - volatile unsigned char sbic_data; /* rw: FIFO top */ - PAD(pad25) - char u0; /* unused, padding */ - PAD(pad26) - char u1; /* unused, padding */ - PAD(pad27) - char u2; /* unused, padding */ - PAD(pad28) - char u3; /* unused, padding */ - PAD(pad29) - char u4; /* unused, padding */ - PAD(pad30) - volatile unsigned char sbic_asr; /* r : Aux Status Register */ - PAD(pad31) - -} sbic_padded_mux_regmap_t; - -typedef struct { - volatile unsigned char sbic_asr; /* r : Aux Status Register */ -/*#define sbic_address sbic_asr /* w : desired register no */ - PAD(pad0); - volatile unsigned char sbic_value; /* rw: register value */ - PAD(pad1); -} sbic_padded_ind_regmap_t; - -#else /* !PAD */ - -typedef sbic_mux_regmap_t sbic_padded_mux_regmap_t; -typedef sbic_ind_regmap_t sbic_padded_ind_regmap_t; - -#endif /* !PAD */ - -/* - * Could have used some non-ANSIsm in the following :-)) - */ -#ifdef SBIC_MUX_ADDRESSING - -typedef sbic_padded_mux_regmap_t sbic_padded_regmap_t; - -#define SET_SBIC_myid(regs,val) (regs)->sbic_myid = (val) -#define GET_SBIC_myid(regs,val) (val) = (regs)->sbic_myid -#define SET_SBIC_cdbsize(regs,val) (regs)->sbic_cdbsize = (val) -#define GET_SBIC_cdbsize(regs,val) (val) = (regs)->sbic_cdbsize -#define SET_SBIC_control(regs,val) (regs)->sbic_control = (val) -#define GET_SBIC_control(regs,val) (val) = (regs)->sbic_control -#define SET_SBIC_timeo(regs,val) (regs)->sbic_timeo = (val) -#define GET_SBIC_timeo(regs,val) (val) = (regs)->sbic_timeo -#define SET_SBIC_cdb1(regs,val) (regs)->sbic_cdb1 = (val) -#define GET_SBIC_cdb1(regs,val) (val) = (regs)->sbic_cdb1 -#define SET_SBIC_cdb2(regs,val) (regs)->sbic_cdb2 = (val) -#define GET_SBIC_cdb2(regs,val) (val) = (regs)->sbic_cdb2 -#define SET_SBIC_cdb3(regs,val) (regs)->sbic_cdb3 = (val) -#define GET_SBIC_cdb3(regs,val) (val) = (regs)->sbic_cdb3 -#define SET_SBIC_cdb4(regs,val) (regs)->sbic_cdb4 = (val) -#define GET_SBIC_cdb4(regs,val) (val) = (regs)->sbic_cdb4 -#define SET_SBIC_cdb5(regs,val) (regs)->sbic_cdb5 = (val) -#define GET_SBIC_cdb5(regs,val) (val) = (regs)->sbic_cdb5 -#define SET_SBIC_cdb6(regs,val) (regs)->sbic_cdb6 = (val) -#define GET_SBIC_cdb6(regs,val) (val) = (regs)->sbic_cdb6 -#define SET_SBIC_cdb7(regs,val) (regs)->sbic_cdb7 = (val) -#define GET_SBIC_cdb7(regs,val) (val) = (regs)->sbic_cdb7 -#define SET_SBIC_cdb8(regs,val) (regs)->sbic_cdb8 = (val) -#define GET_SBIC_cdb8(regs,val) (val) = (regs)->sbic_cdb8 -#define SET_SBIC_cdb9(regs,val) (regs)->sbic_cdb9 = (val) -#define GET_SBIC_cdb9(regs,val) (val) = (regs)->sbic_cdb9 -#define SET_SBIC_cdb10(regs,val) (regs)->sbic_cdb10 = (val) -#define GET_SBIC_cdb10(regs,val) (val) = (regs)->sbic_cdb10 -#define SET_SBIC_cdb11(regs,val) (regs)->sbic_cdb11 = (val) -#define GET_SBIC_cdb11(regs,val) (val) = (regs)->sbic_cdb11 -#define SET_SBIC_cdb12(regs,val) (regs)->sbic_cdb12 = (val) -#define GET_SBIC_cdb12(regs,val) (val) = (regs)->sbic_cdb12 -#define SET_SBIC_tlun(regs,val) (regs)->sbic_tlun = (val) -#define GET_SBIC_tlun(regs,val) (val) = (regs)->sbic_tlun -#define SET_SBIC_cmd_phase(regs,val) (regs)->sbic_cmd_phase = (val) -#define GET_SBIC_cmd_phase(regs,val) (val) = (regs)->sbic_cmd_phase -#define SET_SBIC_syn(regs,val) (regs)->sbic_syn = (val) -#define GET_SBIC_syn(regs,val) (val) = (regs)->sbic_syn -#define SET_SBIC_count_hi(regs,val) (regs)->sbic_count_hi = (val) -#define GET_SBIC_count_hi(regs,val) (val) = (regs)->sbic_count_hi -#define SET_SBIC_count_med(regs,val) (regs)->sbic_count_med = (val) -#define GET_SBIC_count_med(regs,val) (val) = (regs)->sbic_count_med -#define SET_SBIC_count_lo(regs,val) (regs)->sbic_count_lo = (val) -#define GET_SBIC_count_lo(regs,val) (val) = (regs)->sbic_count_lo -#define SET_SBIC_selid(regs,val) (regs)->sbic_selid = (val) -#define GET_SBIC_selid(regs,val) (val) = (regs)->sbic_selid -#define SET_SBIC_rselid(regs,val) (regs)->sbic_rselid = (val) -#define GET_SBIC_rselid(regs,val) (val) = (regs)->sbic_rselid -#define SET_SBIC_csr(regs,val) (regs)->sbic_csr = (val) -#define GET_SBIC_csr(regs,val) (val) = (regs)->sbic_csr -#define SET_SBIC_cmd(regs,val) (regs)->sbic_cmd = (val) -#define GET_SBIC_cmd(regs,val) (val) = (regs)->sbic_cmd -#define SET_SBIC_data(regs,val) (regs)->sbic_data = (val) -#define GET_SBIC_data(regs,val) (val) = (regs)->sbic_data - -#define SBIC_TC_SET(regs,val) { \ - (regs)->sbic_count_hi = ((val)>>16)); \ - (regs)->sbic_count_med = (val)>>8; \ - (regs)->sbic_count_lo = (val); \ - } -#define SBIC_TC_GET(regs,val) { \ - (val) = ((regs)->sbic_count_hi << 16) | \ - ((regs)->sbic_count_med << 8) | \ - ((regs)->sbic_count_lo); \ - } - -#define SBIC_LOAD_COMMAND(regs,cmd,cmdsize) { \ - register char *ptr = (char*)(cmd); \ - (regs)->cis_cdb1 = *ptr++; \ - (regs)->cis_cdb2 = *ptr++; \ - (regs)->cis_cdb3 = *ptr++; \ - (regs)->cis_cdb4 = *ptr++; \ - (regs)->cis_cdb5 = *ptr++; \ - (regs)->cis_cdb6 = *ptr++; \ - if (cmdsize > 6) { \ - (regs)->cis_cdb7 = *ptr++; \ - (regs)->cis_cdb8 = *ptr++; \ - (regs)->cis_cdb9 = *ptr++; \ - (regs)->cis_cdb10 = *ptr++; \ - } \ - if (cmdsize > 10) { \ - (regs)->cis_cdb11 = *ptr++; \ - (regs)->cis_cdb12 = *ptr; \ - } \ - } - -#else /*SBIC_MUX_ADDRESSING*/ - -typedef sbic_padded_ind_regmap_t sbic_padded_regmap_t; - -#define SET_SBIC_myid(regs,val) sbic_write_reg(regs,SBIC_myid,val) -#define GET_SBIC_myid(regs,val) sbic_read_reg(regs,SBIC_myid,val) -#define SET_SBIC_cdbsize(regs,val) sbic_write_reg(regs,SBIC_cdbsize,val) -#define GET_SBIC_cdbsize(regs,val) sbic_read_reg(regs,SBIC_cdbsize,val) -#define SET_SBIC_control(regs,val) sbic_write_reg(regs,SBIC_control,val) -#define GET_SBIC_control(regs,val) sbic_read_reg(regs,SBIC_control,val) -#define SET_SBIC_timeo(regs,val) sbic_write_reg(regs,SBIC_timeo,val) -#define GET_SBIC_timeo(regs,val) sbic_read_reg(regs,SBIC_timeo,val) -#define SET_SBIC_cdb1(regs,val) sbic_write_reg(regs,SBIC_cdb1,val) -#define GET_SBIC_cdb1(regs,val) sbic_read_reg(regs,SBIC_cdb1,val) -#define SET_SBIC_cdb2(regs,val) sbic_write_reg(regs,SBIC_cdb2,val) -#define GET_SBIC_cdb2(regs,val) sbic_read_reg(regs,SBIC_cdb2,val) -#define SET_SBIC_cdb3(regs,val) sbic_write_reg(regs,SBIC_cdb3,val) -#define GET_SBIC_cdb3(regs,val) sbic_read_reg(regs,SBIC_cdb3,val) -#define SET_SBIC_cdb4(regs,val) sbic_write_reg(regs,SBIC_cdb4,val) -#define GET_SBIC_cdb4(regs,val) sbic_read_reg(regs,SBIC_cdb4,val) -#define SET_SBIC_cdb5(regs,val) sbic_write_reg(regs,SBIC_cdb5,val) -#define GET_SBIC_cdb5(regs,val) sbic_read_reg(regs,SBIC_cdb5,val) -#define SET_SBIC_cdb6(regs,val) sbic_write_reg(regs,SBIC_cdb6,val) -#define GET_SBIC_cdb6(regs,val) sbic_read_reg(regs,SBIC_cdb6,val) -#define SET_SBIC_cdb7(regs,val) sbic_write_reg(regs,SBIC_cdb7,val) -#define GET_SBIC_cdb7(regs,val) sbic_read_reg(regs,SBIC_cdb7,val) -#define SET_SBIC_cdb8(regs,val) sbic_write_reg(regs,SBIC_cdb8,val) -#define GET_SBIC_cdb8(regs,val) sbic_read_reg(regs,SBIC_cdb8,val) -#define SET_SBIC_cdb9(regs,val) sbic_write_reg(regs,SBIC_cdb9,val) -#define GET_SBIC_cdb9(regs,val) sbic_read_reg(regs,SBIC_cdb9,val) -#define SET_SBIC_cdb10(regs,val) sbic_write_reg(regs,SBIC_cdb10,val) -#define GET_SBIC_cdb10(regs,val) sbic_read_reg(regs,SBIC_cdb10,val) -#define SET_SBIC_cdb11(regs,val) sbic_write_reg(regs,SBIC_cdb11,val) -#define GET_SBIC_cdb11(regs,val) sbic_read_reg(regs,SBIC_cdb11,val) -#define SET_SBIC_cdb12(regs,val) sbic_write_reg(regs,SBIC_cdb12,val) -#define GET_SBIC_cdb12(regs,val) sbic_read_reg(regs,SBIC_cdb12,val) -#define SET_SBIC_tlun(regs,val) sbic_write_reg(regs,SBIC_tlun,val) -#define GET_SBIC_tlun(regs,val) sbic_read_reg(regs,SBIC_tlun,val) -#define SET_SBIC_cmd_phase(regs,val) sbic_write_reg(regs,SBIC_cmd_phase,val) -#define GET_SBIC_cmd_phase(regs,val) sbic_read_reg(regs,SBIC_cmd_phase,val) -#define SET_SBIC_syn(regs,val) sbic_write_reg(regs,SBIC_syn,val) -#define GET_SBIC_syn(regs,val) sbic_read_reg(regs,SBIC_syn,val) -#define SET_SBIC_count_hi(regs,val) sbic_write_reg(regs,SBIC_count_hi,val) -#define GET_SBIC_count_hi(regs,val) sbic_read_reg(regs,SBIC_count_hi,val) -#define SET_SBIC_count_med(regs,val) sbic_write_reg(regs,SBIC_count_med,val) -#define GET_SBIC_count_med(regs,val) sbic_read_reg(regs,SBIC_count_med,val) -#define SET_SBIC_count_lo(regs,val) sbic_write_reg(regs,SBIC_count_lo,val) -#define GET_SBIC_count_lo(regs,val) sbic_read_reg(regs,SBIC_count_lo,val) -#define SET_SBIC_selid(regs,val) sbic_write_reg(regs,SBIC_selid,val) -#define GET_SBIC_selid(regs,val) sbic_read_reg(regs,SBIC_selid,val) -#define SET_SBIC_rselid(regs,val) sbic_write_reg(regs,SBIC_rselid,val) -#define GET_SBIC_rselid(regs,val) sbic_read_reg(regs,SBIC_rselid,val) -#define SET_SBIC_csr(regs,val) sbic_write_reg(regs,SBIC_csr,val) -#define GET_SBIC_csr(regs,val) sbic_read_reg(regs,SBIC_csr,val) -#define SET_SBIC_cmd(regs,val) sbic_write_reg(regs,SBIC_cmd,val) -#define GET_SBIC_cmd(regs,val) sbic_read_reg(regs,SBIC_cmd,val) -#define SET_SBIC_data(regs,val) sbic_write_reg(regs,SBIC_data,val) -#define GET_SBIC_data(regs,val) sbic_read_reg(regs,SBIC_data,val) - -#define SBIC_TC_SET(regs,val) { \ - sbic_write_reg(regs,SBIC_count_hi,((val)>>16)); \ - (regs)->sbic_value = (val)>>8; wbflush(); \ - (regs)->sbic_value = (val); \ - } -#define SBIC_TC_GET(regs,val) { \ - sbic_read_reg(regs,SBIC_count_hi,(val)); \ - (val) = ((val)<<8) | (regs)->sbic_value; \ - (val) = ((val)<<8) | (regs)->sbic_value; \ - } - -#define SBIC_LOAD_COMMAND(regs,cmd,cmdsize) { - register int n=cmdsize-1; \ - register char *ptr = (char*)(cmd); \ - sbic_write_reg(regs,SBIC_cdb1,*ptr++); \ - while (n-- > 0) (regs)->sbic_value = *ptr++; \ - } - -#endif /*SBIC_MUX_ADDRESSING*/ - -#define GET_SBIC_asr(regs,val) (val) = (regs)->sbic_asr - - -/* - * If all goes well (cross fingers) the typical read/write operation - * should complete in just one interrupt. Therefore our scripts - * have only two parts: a pre-condition and an action. The first - * triggers error handling if not satisfied and in our case it is a match - * of .... - * The action part is just a function pointer, invoked in a standard way. - * The script proceeds only if the action routine returns TRUE. - * See sbic_intr() for how and where this is all done. - */ - -typedef struct script { - struct { /* expected state at interrupt: */ - unsigned char csr; /* interrupt cause */ - unsigned char pha; /* command phase */ - } condition; -/* unsigned char unused[2]; /* unused padding */ - boolean_t (*action)(); /* extra operations */ -} *script_t; - -/* Matching on the condition value */ -#define ANY 0xff -#define SCRIPT_MATCH(csr,pha,cond) \ - (((cond).csr == (csr)) && \ - (((cond).pha == (pha)) || ((cond).pha==ANY))) - - -/* forward decls of script actions */ -boolean_t - sbic_end(), /* all come to an end */ - sbic_get_status(), /* get status from target */ - sbic_dma_in(), /* get data from target via dma */ - sbic_dma_in_r(), /* get data from target via dma (restartable)*/ - sbic_dma_out(), /* send data to target via dma */ - sbic_dma_out_r(), /* send data to target via dma (restartable) */ - sbic_dosynch(), /* negotiate synch xfer */ - sbic_msg_in(), /* receive the disconenct message */ - sbic_disconnected(), /* target has disconnected */ - sbic_reconnect(); /* target reconnected */ - -/* forward decls of error handlers */ -boolean_t - sbic_err_generic(), /* generic handler */ - sbic_err_disconn(), /* target disconnects amidst */ - gimmeabreak(); /* drop into the debugger */ - -int sbic_reset_scsibus(); -boolean_t sbic_probe_target(); -static sbic_wait(); - -/* - * State descriptor for this layer. There is one such structure - * per (enabled) SCSI-33c93 interface - */ -struct sbic_softc { - watchdog_t wd; - sbic_padded_regmap_t *regs; /* 33c93 registers */ - - scsi_dma_ops_t *dma_ops; /* DMA operations and state */ - opaque_t dma_state; - - script_t script; /* what should happen next */ - boolean_t (*error_handler)();/* what if something is wrong */ - int in_count; /* amnt we expect to receive */ - int out_count; /* amnt we are going to ship */ - - volatile char state; -#define SBIC_STATE_BUSY 0x01 /* selecting or currently connected */ -#define SBIC_STATE_TARGET 0x04 /* currently selected as target */ -#define SBIC_STATE_COLLISION 0x08 /* lost selection attempt */ -#define SBIC_STATE_DMA_IN 0x10 /* tgt --> initiator xfer */ -#define SBIC_STATE_AM_MODE 0x20 /* 33c93A with advanced mode (AM) */ - - unsigned char ntargets; /* how many alive on this scsibus */ - unsigned char done; - unsigned char unused; - - scsi_softc_t *sc; /* HBA-indep info */ - target_info_t *active_target; /* the current one */ - - target_info_t *next_target; /* trying to seize bus */ - queue_head_t waiting_targets;/* other targets competing for bus */ - -} sbic_softc_data[NSBIC]; - -typedef struct sbic_softc *sbic_softc_t; - -sbic_softc_t sbic_softc[NSBIC]; - -/* - * Synch xfer parameters, and timing conversions - */ -int sbic_min_period = SBIC_SYN_MIN_PERIOD; /* in cycles = f(ICLK,FSn) */ -int sbic_max_offset = SBIC_SYN_MAX_OFFSET; /* pure number */ - -int sbic_to_scsi_period(regs,a) -{ - unsigned int fs; - - /* cycle = DIV / (2*CLK) */ - /* DIV = FS+2 */ - /* best we can do is 200ns at 20Mhz, 2 cycles */ - - GET_SBIC_myid(regs,fs); - fs = (fs >>6) + 2; /* DIV */ - fs = (fs * 1000) / (SBIC_CLOCK_FREQUENCY<<1); /* Cycle, in ns */ - if (a < 2) a = 8; /* map to Cycles */ - return ((fs*a)>>2); /* in 4 ns units */ -} - -int scsi_period_to_sbic(regs,p) -{ - register unsigned int fs; - - /* Just the inverse of the above */ - - GET_SBIC_myid(regs,fs); - fs = (fs >>6) + 2; /* DIV */ - fs = (fs * 1000) / (SBIC_CLOCK_FREQUENCY<<1); /* Cycle, in ns */ - - ret = p << 2; /* in ns units */ - ret = ret / fs; /* in Cycles */ - if (ret < sbic_min_period) - return sbic_min_period; - /* verify rounding */ - if (sbic_to_scsi_period(regs,ret) < p) - ret++; - return (ret >= 8) ? 0 : ret; -} - -#define u_min(a,b) (((a) < (b)) ? (a) : (b)) - -/* - * Definition of the controller for the auto-configuration program. - */ - -int sbic_probe(), scsi_slave(), scsi_attach(), sbic_go(), sbic_intr(); - -caddr_t sbic_std[NSBIC] = { 0 }; -struct bus_device *sbic_dinfo[NSBIC*8]; -struct bus_ctlr *sbic_minfo[NSBIC]; -struct bus_driver sbic_driver = - { sbic_probe, scsi_slave, scsi_attach, sbic_go, sbic_std, "rz", sbic_dinfo, - "sbic", sbic_minfo, BUS_INTR_B4_PROBE}; - - -sbic_set_dmaops(unit, dmaops) - unsigned int unit; - scsi_dma_ops_t *dmaops; -{ - if (unit < NSBIC) - sbic_std[unit] = (caddr_t)dmaops; -} - -/* - * Scripts - */ -struct script -sbic_script_any_cmd[] = { /* started with SEL & XFER */ - {{SBIC_CSR_S_XFERRED, 0x60}, sbic_get_status}, -}, - -sbic_script_try_synch[] = { /* started with SEL */ - {{SBIC_CSR_INITIATOR, ANY}, sbic_dosynch}, - {{SBIC_CSR_S_XFERRED, 0x60}, sbic_get_status}, -}; - - -#define DEBUG -#ifdef DEBUG - -#define PRINT(x) if (scsi_debug) printf x - -sbic_state(regs, overrule) - sbic_padded_regmap_t *regs; -{ - register unsigned char asr,tmp; - - if (regs == 0) { - if (sbic_softc[0]) - regs = sbic_softc[0]->regs; - else - regs = (sbic_padded_regmap_t*)0xXXXXXXXX; - } - - GET_SBIC_asr(regs,asr); - - if ((asr & SBIC_ASR_BSY) && !overrule) - db_printf("-BUSY- "); - else { - unsigned char tlun,pha,selid,rselid; - unsigned int cnt; - GET_SBIC_tlun(regs,tlun); - GET_SBIC_cmd_phase(regs,pha); - GET_SBIC_selid(regs,selid); - GET_SBIC_rselid(regs,rselid); - SBIC_TC_GET(regs,cnt); - db_printf("tc %x tlun %x sel %x rsel %x pha %x ", - cnt, tlun, selid, rselid, pha); - } - - if (asr & SBIC_ASR_INT) - db_printf("-INT- "); - else { - GET_SBIC_csr(regs,tmp); - db_printf("csr %x ", tmp); - } - - if (asr & SBIC_ASR_CIP) - db_printf("-CIP-\n"); - else { - GET_SBIC_cmd(regs,tmp); - db_printf("cmd %x\n", tmp); - } - return 0; -} - -sbic_target_state(tgt) - target_info_t *tgt; -{ - if (tgt == 0) - tgt = sbic_softc[0]->active_target; - if (tgt == 0) - return 0; - db_printf("@x%x: fl %x dma %X+%x cmd %x@%X id %x per %x off %x ior %X ret %X\n", - tgt, - tgt->flags, tgt->dma_ptr, tgt->transient_state.dma_offset, tgt->cur_cmd, - tgt->cmd_ptr, tgt->target_id, tgt->sync_period, tgt->sync_offset, - tgt->ior, tgt->done); - if (tgt->flags & TGT_DISCONNECTED){ - script_t spt; - - spt = tgt->transient_state.script; - db_printf("disconnected at "); - db_printsym(spt,1); - db_printf(": %x %x ", spt->condition.csr, spt->condition.pha); - db_printsym(spt->action,1); - db_printf(", "); - db_printsym(tgt->transient_state.handler, 1); - db_printf("\n"); - } - - return 0; -} - -sbic_all_targets(unit) -{ - int i; - target_info_t *tgt; - for (i = 0; i < 8; i++) { - tgt = sbic_softc[unit]->sc->target[i]; - if (tgt) - sbic_target_state(tgt); - } -} - -sbic_script_state(unit) -{ - script_t spt = sbic_softc[unit]->script; - - if (spt == 0) return 0; - db_printsym(spt,1); - db_printf(": %x %x ", spt->condition.csr, spt->condition.pha); - db_printsym(spt->action,1); - db_printf(", "); - db_printsym(sbic_softc[unit]->error_handler, 1); - return 0; -} - -#define TRMAX 200 -int tr[TRMAX+3]; -int trpt, trpthi; -#define TR(x) tr[trpt++] = x -#define TRWRAP trpthi = trpt; trpt = 0; -#define TRCHECK if (trpt > TRMAX) {TRWRAP} - -#define TRACE - -#ifdef TRACE - -#define LOGSIZE 256 -int sbic_logpt; -char sbic_log[LOGSIZE]; - -#define MAXLOG_VALUE 0x1e -struct { - char *name; - unsigned int count; -} logtbl[MAXLOG_VALUE]; - -static LOG(e,f) - char *f; -{ - sbic_log[sbic_logpt++] = (e); - if (sbic_logpt == LOGSIZE) sbic_logpt = 0; - if ((e) < MAXLOG_VALUE) { - logtbl[(e)].name = (f); - logtbl[(e)].count++; - } -} - -sbic_print_log(skip) - int skip; -{ - register int i, j; - register unsigned char c; - - for (i = 0, j = sbic_logpt; i < LOGSIZE; i++) { - c = sbic_log[j]; - if (++j == LOGSIZE) j = 0; - if (skip-- > 0) - continue; - if (c < MAXLOG_VALUE) - db_printf(" %s", logtbl[c].name); - else - db_printf("-x%x", c & 0x7f); - } -} - -sbic_print_stat() -{ - register int i; - register char *p; - for (i = 0; i < MAXLOG_VALUE; i++) { - if (p = logtbl[i].name) - printf("%d %s\n", logtbl[i].count, p); - } -} - -#else /*TRACE*/ -#define LOG(e,f) -#define LOGSIZE -#endif /*TRACE*/ - -#else /*DEBUG*/ -#define PRINT(x) -#define LOG(e,f) -#define LOGSIZE - -#endif /*DEBUG*/ - - -/* - * Probe/Slave/Attach functions - */ - -/* - * Probe routine: - * Should find out (a) if the controller is - * present and (b) which/where slaves are present. - * - * Implementation: - * Send a test-unit-ready to each possible target on the bus - * except of course ourselves. - */ -sbic_probe(reg, ui) - unsigned reg; - struct bus_ctlr *ui; -{ - int unit = ui->unit; - sbic_softc_t sbic = &sbic_softc_data[unit]; - int target_id; - scsi_softc_t *sc; - register sbic_padded_regmap_t *regs; - spl_t s; - boolean_t did_banner = FALSE; - - /* - * We are only called if the right board is there, - * but make sure anyways.. - */ - if (check_memory(reg, 0)) - return 0; - -#if MAPPABLE - /* Mappable version side */ - SBIC_probe(reg, ui); -#endif /*MAPPABLE*/ - - /* - * Initialize hw descriptor, cache some pointers - */ - sbic_softc[unit] = sbic; - sbic->regs = (sbic_padded_regmap_t *) (reg); - - if ((sbic->dma_ops = (scsi_dma_ops_t *)sbic_std[unit]) == 0) - /* use same as unit 0 if undefined */ - sbic->dma_ops = (scsi_dma_ops_t *)sbic_std[0]; - - sbic->dma_state = (*sbic->dma_ops->init)(unit, reg); - - queue_init(&sbic->waiting_targets); - - sc = scsi_master_alloc(unit, sbic); - sbic->sc = sc; - - sc->go = sbic_go; - sc->watchdog = scsi_watchdog; - sc->probe = sbic_probe_target; - sbic->wd.reset = sbic_reset_scsibus; - -#ifdef MACH_KERNEL - sc->max_dma_data = -1; -#else - sc->max_dma_data = scsi_per_target_virtual; -#endif - - regs = sbic->regs; - - /* - * Reset chip, fully. Note that interrupts are already enabled. - */ - s = splbio(); - if (sbic_reset(regs, TRUE)) - sbic->state |= SBIC_STATE_AM_MODE; - - /* - * Our SCSI id on the bus. - * The user can probably set this via the prom. - * If not, it is easy to fix: make a default that - * can be changed as boot arg. Otherwise we keep - * what the prom used. - */ -#ifdef unneeded - SET_SBIC_myid(regs, (scsi_initiator_id[unit] & 0x7)); - sbic_reset(regs, TRUE); -#endif - GET_SBIC_myid(regs,sc->initiator_id); - sc->initiator_id &= 0x7; - printf("%s%d: SCSI id %d", ui->name, unit, sc->initiator_id); - - /* - * For all possible targets, see if there is one and allocate - * a descriptor for it if it is there. - */ - for (target_id = 0; target_id < 8; target_id++) { - register unsigned char asr, csr, pha; - register scsi_status_byte_t status; - - /* except of course ourselves */ - if (target_id == sc->initiator_id) - continue; - - SBIC_TC_SET(regs,0); - SET_SBIC_selid(regs,target_id); - SET_SBIC_timo(regs,SBIC_TIMEOUT(250,SBIC_CLOCK_FREQUENCY)); - - /* - * See if the unit is ready. - * XXX SHOULD inquiry LUN 0 instead !!! - */ - { - scsi_command_test_unit_ready_y c; - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_TEST_UNIT_READY; - SBIC_LOAD_COMMAND(regs,&c,sizeof(c)); - } - - /* select and send it */ - SET_SBIC_cmd(regs,SBIC_CMD_SEL_XFER); - - /* wait for the chip to complete, or timeout */ - asr = sbic_wait(regs, SBIC_ASR_INT); - GET_SBIC_csr(regs,csr); - - /* - * Check if the select timed out - */ - GET_SBIC_cmd_phase(regs,pha); - if ((SBIC_CPH(pha) == 0) && (csr & SBIC_CSR_CMD_ERR)) { - /* noone out there */ -#if notsure - SET_SBIC_cmd(regs,SBIC_CMD_DISC); - asr = sbic_wait(regs, SBIC_ASR_INT); - GET_SBIC_csr(regs,csr); -#endif - continue; - } - - printf(",%s%d", did_banner++ ? " " : " target(s) at ", - target_id); - - if (SBIC_CPH(pha) < 0x60) - /* XXX recover by hand XXX */ - panic(" target acts weirdo"); - - GET_SBIC_tlun(regs,status.bits); - - if (status.st.scsi_status_code != SCSI_ST_GOOD) - scsi_error( 0, SCSI_ERR_STATUS, status.bits, 0); - - /* - * Found a target - */ - sbic->ntargets++; - { - register target_info_t *tgt; - tgt = scsi_slave_alloc(sc->masterno, target_id, sbic); - - (*sbic->dma_ops->new_target)(sbic->dma_state, tgt); - } - } - - printf(".\n"); - - splx(s); - return 1; -} - -boolean_t -sbic_probe_target(tgt, ior) - target_info_t *tgt; - io_req_t ior; -{ - sbic_softc_t sbic = sbic_softc[tgt->masterno]; - boolean_t newlywed; - - newlywed = (tgt->cmd_ptr == 0); - if (newlywed) { - (*sbic->dma_ops->new_target)(sbic->dma_state, tgt); - } - - if (scsi_inquiry(tgt, SCSI_INQ_STD_DATA) == SCSI_RET_DEVICE_DOWN) - return FALSE; - - tgt->flags = TGT_ALIVE; - return TRUE; -} - -static sbic_wait(regs, until) - sbic_padded_regmap_t *regs; - char until; -{ - register unsigned char val; - int timeo = 1000000; - - GET_SBIC_asr(regs,val); - while ((val & until) == 0) { - if (!timeo--) { - printf("sbic_wait TIMEO with x%x\n", regs->sbic_csr); - break; - } - delay(1); - GET_SBIC_asr(regs,val); - } - return val; -} - -boolean_t -sbic_reset(regs, quick) - sbic_padded_regmap_t *regs; -{ - char my_id, csr; - - /* preserve our ID for now */ - GET_SBIC_myid(regs,my_id); - my_id &= SBIC_ID_MASK; - - if (SBIC_CLOCK_FREQUENCY < 11) - my_id |= SBIC_ID_FS_8_10; - else if (SBIC_CLOCK_FREQUENCY < 16) - my_id |= SBIC_ID_FS_12_15; - else if (SBIC_CLOCK_FREQUENCY < 21) - my_id |= SBIC_ID_FS_16_20; - - my_id |= SBIC_ID_EAF|SBIC_ID_EHP; - - SET_SBIC_myid(regs,myid); - wbflush(); - - /* - * Reset chip and wait till done - */ - SET_SBIC_cmd(regs,SBIC_CMD_RESET); - delay(25); - - (void) sbic_wait(regs, SBIC_ASR_INT); - GET_SBIC_csr(regs,csr); /* clears interrupt also */ - - /* - * Set up various chip parameters - */ - SET_SBIC_control(regs, SBIC_CTL_HHP|SBIC_CTL_EDI|SBIC_CTL_HSP| - SBIC_MACHINE_DMA_MODE); - /* will do IDI on the fly */ - SET_SBIC_rselid(regs, SBIC_RID_ER|SBIC_RID_ES|SBIC_RID_DSP); - SET_SBIC_syn(regs,SBIC_SYN(0,sbic_min_period)); /* asynch for now */ - - /* anything else was zeroed by reset */ - - if (quick) - return (csr & SBIC_CSR_RESET_AM); - - /* - * reset the scsi bus, the interrupt routine does the rest - * or you can call sbic_bus_reset(). - */ - /* - * Now HOW do I do this ? I just want to drive the SCSI "RST" - * signal true for about 25 usecs; But the chip has no notion - * of such a signal at all. The spec suggest that the chip's - * reset pin be connected to the RST signal, which makes this - * operation a machdep one. - */ - SBIC_MACHINE_RESET_SCSIBUS(regs, 30); - - return (csr & SBIC_CSR_RESET_AM); -} - -/* - * Operational functions - */ - -/* - * Start a SCSI command on a target - */ -sbic_go(tgt, cmd_count, in_count, cmd_only) - target_info_t *tgt; - boolean_t cmd_only; -{ - sbic_softc_t sbic; - register spl_t s; - boolean_t disconn; - script_t scp; - boolean_t (*handler)(); - - LOG(1,"go"); - - sbic = (sbic_softc_t)tgt->hw_state; - - tgt->transient_state.cmd_count = cmd_count; /* keep it here */ - - (*sbic->dma_ops->map)(sbic->dma_state, tgt); - - disconn = BGET(scsi_might_disconnect,tgt->masterno,tgt->target_id); - disconn = disconn && (sbic->ntargets > 1); - disconn |= BGET(scsi_should_disconnect,tgt->masterno,tgt->target_id); - - /* - * Setup target state - */ - tgt->done = SCSI_RET_IN_PROGRESS; - - handler = (disconn) ? sbic_err_disconn : sbic_err_generic; - scp = sbic_script_any_cmd; - - switch (tgt->cur_cmd) { - case SCSI_CMD_READ: - case SCSI_CMD_LONG_READ: - LOG(2,"readop"); - break; - case SCSI_CMD_WRITE: - case SCSI_CMD_LONG_WRITE: - LOG(0x1a,"writeop"); - break; - case SCSI_CMD_INQUIRY: - /* This is likely the first thing out: - do the synch neg if so */ - if (!cmd_only && ((tgt->flags&TGT_DID_SYNCH)==0)) { - scp = sbic_script_try_synch; - tgt->flags |= TGT_TRY_SYNCH; - break; - } - case SCSI_CMD_MODE_SELECT: - case SCSI_CMD_REASSIGN_BLOCKS: - case SCSI_CMD_FORMAT_UNIT: - tgt->transient_state.cmd_count = sizeof(scsi_command_group_0); - tgt->transient_state.out_count = cmd_count - sizeof(scsi_command_group_0); - /* fall through */ - case SCSI_CMD_REQUEST_SENSE: - case SCSI_CMD_MODE_SENSE: - case SCSI_CMD_RECEIVE_DIAG_RESULTS: - case SCSI_CMD_READ_CAPACITY: - case SCSI_CMD_READ_BLOCK_LIMITS: - case SCSI_CMD_READ_TOC: - case SCSI_CMD_READ_SUBCH: - case SCSI_CMD_READ_HEADER: - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - case SCSI_CMD_TEST_UNIT_READY: - /* - * Do the synch negotiation here, unless prohibited - * or done already - */ - if ( ! (tgt->flags & TGT_DID_SYNCH)) { - scp = sbic_script_try_synch; - tgt->flags |= TGT_TRY_SYNCH; - cmd_only = FALSE; - } - /* fall through */ - default: - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - } - - tgt->transient_state.script = scp; - tgt->transient_state.handler = handler; - tgt->transient_state.identify = (cmd_only) ? 0xff : - (disconn ? SCSI_IDENTIFY|SCSI_IFY_ENABLE_DISCONNECT : - SCSI_IDENTIFY); - - if (in_count) - tgt->transient_state.in_count = - (in_count < tgt->block_size) ? tgt->block_size : in_count; - else - tgt->transient_state.in_count = 0; - - /* - * See if another target is currently selected on - * this SCSI bus, e.g. lock the sbic structure. - * Note that it is the strategy routine's job - * to serialize ops on the same target as appropriate. - * XXX here and everywhere, locks! - */ - /* - * Protection viz reconnections makes it tricky. - */ - s = splbio(); - - if (sbic->wd.nactive++ == 0) - sbic->wd.watchdog_state = SCSI_WD_ACTIVE; - - if (sbic->state & SBIC_STATE_BUSY) { - /* - * Queue up this target, note that this takes care - * of proper FIFO scheduling of the scsi-bus. - */ - LOG(3,"enqueue"); - enqueue_tail(&sbic->waiting_targets, (queue_entry_t) tgt); - } else { - /* - * It is down to at most two contenders now, - * we will treat reconnections same as selections - * and let the scsi-bus arbitration process decide. - */ - sbic->state |= SBIC_STATE_BUSY; - sbic->next_target = tgt; - sbic_attempt_selection(sbic); - /* - * Note that we might still lose arbitration.. - */ - } - splx(s); -} - -sbic_attempt_selection(sbic) - sbic_softc_t sbic; -{ - target_info_t *tgt; - sbic_padded_regmap_t *regs; - register unsigned char val; - register int out_count; - - regs = sbic->regs; - tgt = sbic->next_target; - - LOG(4,"select"); - LOG(0x80+tgt->target_id,0); - - /* - * We own the bus now.. unless we lose arbitration - */ - sbic->active_target = tgt; - - /* Try to avoid reselect collisions */ - GET_SBIC_asr(regs,val); - if (val & SBIC_ASR_INT) - return; - - /* - * Init bus state variables - */ - sbic->script = tgt->transient_state.script; - sbic->error_handler = tgt->transient_state.handler; - sbic->done = SCSI_RET_IN_PROGRESS; - - sbic->out_count = 0; - sbic->in_count = 0; - - /* Define how the identify msg should be built */ - GET_SBIC_rselid(regs, val); - val &= ~(SBIC_RID_MASK|SBIC_RID_ER); - /* the enable reselection bit is used to build the identify msg */ - if (tgt->transient_state.identify != 0xff) - val |= (tgt->transient_state.identify & SCSI_IFY_ENABLE_DISCONNECT) << 1; - SET_SBIC_rselid(regs, val); - SET_SBIC_tlun(regs, tgt->lun); - - /* - * Start the chip going - */ - out_count = (*sbic->dma_ops->start_cmd)(sbic->dma_state, tgt); - SBIC_TC_PUT(regs, out_count); - - val = tgt->target_id; - if (tgt->transient_state.in_count) - val |= SBIC_SID_FROM_SCSI; - SET_SBIC_selid(regs, val); - - SET_SBIC_timo(regs,SBIC_TIMEOUT(250,SBIC_CLOCK_FREQUENCY)); - - SET_SBIC_syn(regs,SBIC_SYN(tgt->sync_offset,tgt->sync_period)); - - /* ugly little help for compiler */ -#define command out_count - if (tgt->flags & TGT_DID_SYNCH) { - command = (tgt->transient_state.identify == 0xff) ? - SBIC_CMD_SEL_XFER : - SBIC_CMD_SEL_ATN_XFER; /*preferred*/ - } else if (tgt->flags & TGT_TRY_SYNCH) - command = SBIC_CMD_SEL_ATN; - else - command = SBIC_CMD_SEL_XFER; - - /* load 10 bytes anyways, the chip knows how much to use */ - SBIC_LOAD_COMMAND(regs, tgt->cmd_ptr, 10); - - /* Try to avoid reselect collisions */ - GET_SBIC_asr(regs,val); - if (val & SBIC_ASR_INT) - return; - - SET_SBIC_cmd_phase(regs, 0); /* not a resume */ - SET_SBIC_cmd(regs, command); -#undef command -} - -/* - * Interrupt routine - * Take interrupts from the chip - * - * Implementation: - * Move along the current command's script if - * all is well, invoke error handler if not. - */ -sbic_intr(unit, spllevel) - spl_t spllevel; -{ - register sbic_softc_t sbic; - register script_t scp; - register int asr, csr, pha; - register sbic_padded_regmap_t *regs; -#if MAPPABLE - extern boolean_t rz_use_mapped_interface; - - if (rz_use_mapped_interface) - return SBIC_intr(unit,spllevel); -#endif /*MAPPABLE*/ - - sbic = sbic_softc[unit]; - regs = sbic->regs; - - LOG(5,"\n\tintr"); - - /* drop spurious interrupts */ - GET_SBIC_asr(regs, asr); - if ((asr & SBIC_ASR_INT) == 0) - return; - - /* collect ephemeral information */ - GET_SBIC_cmd_phase(regs, pha); - GET_SBIC_csr(regs, csr); - -TR(csr);TR(asr);TR(pha);TRCHECK - - /* XXX verify this is indeed the case for a SCSI RST asserted */ - if ((csr & SBIC_CSR_CAUSE) == SBIC_CSR_RESET) - return sbic_bus_reset(sbic); - - /* we got an interrupt allright */ - if (sbic->active_target) - sbic->wd.watchdog_state = SCSI_WD_ACTIVE; - - splx(spllevel); /* drop priority */ - - if ((sbic->state & SBIC_STATE_TARGET) || - (csr == SBIC_CSR_RSLT_AM) || (csr == SBIC_CSR_RSLT_NOAM) || - (csr == SBIC_CSR_SLT) || (csr == SBIC_CSR_SLT_ATN)) - return sbic_target_intr(sbic); - - /* - * In attempt_selection() we gave the select command even if - * the chip might have been reconnected already. - */ - if ((csr == SBIC_CSR_RSLT_NI) || (csr == SBIC_CSR_RSLT_IFY)) - return sbic_reconnect(sbic, csr, pha); - - /* - * Check for parity errors - */ - if (asr & SBIC_ASR_PE) { - char *msg; -printf("{PE %x,%x}", asr, pha); - - msg = "SCSI bus parity error"; - /* all we can do is to throw a reset on the bus */ - printf( "sbic%d: %s%s", sbic - sbic_softc_data, msg, - ", attempting recovery.\n"); - sbic_reset(regs, FALSE); - return; - } - - if ((scp = sbic->script) == 0) /* sanity */ - return; - - LOG(6,"match"); - if (SCRIPT_MATCH(csr,pha,scp->condition)) { - /* - * Perform the appropriate operation, - * then proceed - */ - if ((*scp->action)(sbic, csr, pha)) { - sbic->script = scp + 1; - } - } else - return (*sbic->error_handler)(sbic, csr, pha); -} - -sbic_target_intr() -{ - panic("SBIC: TARGET MODE !!!\n"); -} - -/* - * Routines that the interrupt code might switch to - */ - -boolean_t -sbic_end(sbic, csr, pha) - register sbic_softc_t sbic; -{ - register target_info_t *tgt; - register io_req_t ior; - - LOG(8,"end"); - - tgt = sbic->active_target; - if ((tgt->done = sbic->done) == SCSI_RET_IN_PROGRESS) - tgt->done = SCSI_RET_SUCCESS; - - sbic->script = 0; - - if (sbic->wd.nactive-- == 1) - sbic->wd.watchdog_state = SCSI_WD_INACTIVE; - - sbic_release_bus(sbic); - - if (ior = tgt->ior) { - (*sbic->dma_ops->end_cmd)(sbic->dma_state, tgt, ior); - LOG(0xA,"ops->restart"); - (*tgt->dev_ops->restart)( tgt, TRUE); - } - - return FALSE; -} - -boolean_t -sbic_release_bus(sbic) - register sbic_softc_t sbic; -{ - boolean_t ret = TRUE; - - LOG(9,"release"); - if (sbic->state & SBIC_STATE_COLLISION) { - - LOG(0xB,"collided"); - sbic->state &= ~SBIC_STATE_COLLISION; - sbic_attempt_selection(sbic); - - } else if (queue_empty(&sbic->waiting_targets)) { - - sbic->state &= ~SBIC_STATE_BUSY; - sbic->active_target = 0; - sbic->script = 0; - ret = FALSE; - - } else { - - LOG(0xC,"dequeue"); - sbic->next_target = (target_info_t *) - dequeue_head(&sbic->waiting_targets); - sbic_attempt_selection(sbic); - } - return ret; -} - -boolean_t -sbic_get_status(sbic, csr, pha) - register sbic_softc_t sbic; -{ - register sbic_padded_regmap_t *regs = sbic->regs; - register scsi2_status_byte_t status; - int len; - io_req_t ior; - register target_info_t *tgt = sbic->active_target; - - LOG(0xD,"get_status"); -TRWRAP - - sbic->state &= ~SBIC_STATE_DMA_IN; - - /* - * Get the status byte - */ - GET_SBIC_tlun(regs, status.bits); - - if (status.st.scsi_status_code != SCSI_ST_GOOD) { - scsi_error(sbic->active_target, SCSI_ERR_STATUS, status.bits, 0); - sbic->done = (status.st.scsi_status_code == SCSI_ST_BUSY) ? - SCSI_RET_RETRY : SCSI_RET_NEED_SENSE; - } else - sbic->done = SCSI_RET_SUCCESS; - - /* Tell DMA engine we are done */ - (*sbic->dma_ops->end_xfer)(sbic->dma_state, tgt, tgt->transient_state.in_count); - - return sbic_end(sbic, csr, pha); - -} - -#if 0 - -boolean_t -sbic_dma_in(sbic, csr, ir) - register sbic_softc_t sbic; -{ - register target_info_t *tgt; - register sbic_padded_regmap_t *regs = sbic->regs; - register int count; - unsigned char ff = regs->sbic_flags; - - LOG(0xE,"dma_in"); - tgt = sbic->active_target; - - sbic->state |= SBIC_STATE_DMA_IN; - - count = (*sbic->dma_ops->start_datain)(sbic->dma_state, tgt); - SBIC_TC_PUT(regs, count); - - if ((sbic->in_count = count) == tgt->transient_state.in_count) - return TRUE; - regs->sbic_cmd = sbic->script->command; - sbic->script = sbic_script_restart_data_in; - return FALSE; -} - -sbic_dma_in_r(sbic, csr, ir) - register sbic_softc_t sbic; -{ - register target_info_t *tgt; - register sbic_padded_regmap_t *regs = sbic->regs; - register int count; - boolean_t advance_script = TRUE; - - - LOG(0xE,"dma_in"); - tgt = sbic->active_target; - - sbic->state |= SBIC_STATE_DMA_IN; - - if (sbic->in_count == 0) { - /* - * Got nothing yet, we just reconnected. - */ - register int avail; - - /* - * Rather than using the messy RFB bit in cnfg2 - * (which only works for synch xfer anyways) - * we just bump up the dma offset. We might - * endup with one more interrupt at the end, - * so what. - * This is done in sbic_err_disconn(), this - * way dma (of msg bytes too) is always aligned - */ - - count = (*sbic->dma_ops->restart_datain_1) - (sbic->dma_state, tgt); - - /* common case of 8k-or-less read ? */ - advance_script = (tgt->transient_state.in_count == count); - - } else { - - /* - * We received some data. - */ - register int offset, xferred; - - /* - * Problem: sometimes we get a 'spurious' interrupt - * right after a reconnect. It goes like disconnect, - * reconnect, dma_in_r, here but DMA is still rolling. - * Since there is no good reason we got here to begin with - * we just check for the case and dismiss it: we should - * get another interrupt when the TC goes to zero or the - * target disconnects. - */ - SBIC_TC_GET(regs,xferred); - if (xferred != 0) - return FALSE; - - xferred = sbic->in_count - xferred; - assert(xferred > 0); - - tgt->transient_state.in_count -= xferred; - assert(tgt->transient_state.in_count > 0); - - count = (*sbic->dma_ops->restart_datain_2) - (sbic->dma_state, tgt, xferred); - - sbic->in_count = count; - SBIC_TC_PUT(regs, count); - regs->sbic_cmd = sbic->script->command; - - (*sbic->dma_ops->restart_datain_3) - (sbic->dma_state, tgt); - - /* last chunk ? */ - if (count == tgt->transient_state.in_count) - sbic->script++; - - return FALSE; - } - - sbic->in_count = count; - SBIC_TC_PUT(regs, count); - - if (!advance_script) { - regs->sbic_cmd = sbic->script->command; - } - return advance_script; -} - - -/* send data to target. Only called to start the xfer */ - -boolean_t -sbic_dma_out(sbic, csr, ir) - register sbic_softc_t sbic; -{ - register sbic_padded_regmap_t *regs = sbic->regs; - register int reload_count; - register target_info_t *tgt; - int command; - - LOG(0xF,"dma_out"); - - SBIC_TC_GET(regs, reload_count); - sbic->extra_count = regs->sbic_flags & SBIC_FLAGS_FIFO_CNT; - reload_count += sbic->extra_count; - SBIC_TC_PUT(regs, reload_count); - sbic->state &= ~SBIC_STATE_DMA_IN; - - tgt = sbic->active_target; - - command = sbic->script->command; - - if ((sbic->out_count = reload_count) >= - tgt->transient_state.out_count) - sbic->script++; - else - sbic->script = sbic_script_restart_data_out; - - if ((*sbic->dma_ops->start_dataout) - (sbic->dma_state, tgt, ®s->sbic_cmd, command)) { - regs->sbic_cmd = command; - } - - return FALSE; -} - -/* send data to target. Called in two different ways: - (a) to restart a big transfer and - (b) after reconnection - */ -boolean_t -sbic_dma_out_r(sbic, csr, ir) - register sbic_softc_t sbic; -{ - register sbic_padded_regmap_t *regs = sbic->regs; - register target_info_t *tgt; - boolean_t advance_script = TRUE; - int count; - - - LOG(0xF,"dma_out"); - - tgt = sbic->active_target; - sbic->state &= ~SBIC_STATE_DMA_IN; - - if (sbic->out_count == 0) { - /* - * Nothing committed: we just got reconnected - */ - count = (*sbic->dma_ops->restart_dataout_1) - (sbic->dma_state, tgt); - - /* is this the last chunk ? */ - advance_script = (tgt->transient_state.out_count == count); - } else { - /* - * We sent some data. - */ - register int offset, xferred; - - SBIC_TC_GET(regs,count); - - /* see comment above */ - if (count) { - return FALSE; - } - - count += (regs->sbic_flags & SBIC_FLAGS_FIFO_CNT); - count -= sbic->extra_count; - xferred = sbic->out_count - count; - assert(xferred > 0); - - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - - count = (*sbic->dma_ops->restart_dataout_2) - (sbic->dma_state, tgt, xferred); - - /* last chunk ? */ - if (tgt->transient_state.out_count == count) - goto quickie; - - sbic->out_count = count; - - sbic->extra_count = (*sbic->dma_ops->restart_dataout_3) - (sbic->dma_state, tgt, ®s->sbic_fifo); - SBIC_TC_PUT(regs, count); - regs->sbic_cmd = sbic->script->command; - - (*sbic->dma_ops->restart_dataout_4)(sbic->dma_state, tgt); - - return FALSE; - } - -quickie: - sbic->extra_count = (*sbic->dma_ops->restart_dataout_3) - (sbic->dma_state, tgt, ®s->sbic_fifo); - - sbic->out_count = count; - - SBIC_TC_PUT(regs, count); - - if (!advance_script) { - regs->sbic_cmd = sbic->script->command; - } - return advance_script; -} -#endif /*0*/ - -boolean_t -sbic_dosynch(sbic, csr, pha) - register sbic_softc_t sbic; - register unsigned char csr, pha; -{ - register sbic_padded_regmap_t *regs = sbic->regs; - register unsigned char c; - int i, per, offs; - register target_info_t *tgt; - - /* - * Try synch negotiation - * Phase is MSG_OUT here. - */ - tgt = sbic->active_target; - -#if 0 - regs->sbic_cmd = SBIC_CMD_FLUSH; - delay(2); - - per = sbic_min_period; - if (BGET(scsi_no_synchronous_xfer,sbic->sc->masterno,tgt->target_id)) - offs = 0; - else - offs = sbic_max_offset; - - tgt->flags |= TGT_DID_SYNCH; /* only one chance */ - tgt->flags &= ~TGT_TRY_SYNCH; - - regs->sbic_fifo = SCSI_EXTENDED_MESSAGE; - regs->sbic_fifo = 3; - regs->sbic_fifo = SCSI_SYNC_XFER_REQUEST; - regs->sbic_fifo = sbic_to_scsi_period(regs,sbic_min_period); - regs->sbic_fifo = offs; - regs->sbic_cmd = SBIC_CMD_XFER_INFO; - csr = sbic_wait(regs, SBIC_CSR_INT); - ir = regs->sbic_intr; - - if (SCSI_PHASE(csr) != SCSI_PHASE_MSG_IN) - gimmeabreak(); - - regs->sbic_cmd = SBIC_CMD_XFER_INFO; - csr = sbic_wait(regs, SBIC_CSR_INT); - ir = regs->sbic_intr; - - while ((regs->sbic_flags & SBIC_FLAGS_FIFO_CNT) > 0) - c = regs->sbic_fifo; /* see what it says */ - - if (c == SCSI_MESSAGE_REJECT) { - printf(" did not like SYNCH xfer "); - - /* Tk50s get in trouble with ATN, sigh. */ - regs->sbic_cmd = SBIC_CMD_CLR_ATN; - - goto cmd; - } - - /* - * Receive the rest of the message - */ - regs->sbic_cmd = SBIC_CMD_MSG_ACPT; - sbic_wait(regs, SBIC_CSR_INT); - ir = regs->sbic_intr; - - if (c != SCSI_EXTENDED_MESSAGE) - gimmeabreak(); - - regs->sbic_cmd = SBIC_CMD_XFER_INFO; - sbic_wait(regs, SBIC_CSR_INT); - c = regs->sbic_intr; - if (regs->sbic_fifo != 3) - panic("sbic_dosynch"); - - for (i = 0; i < 3; i++) { - regs->sbic_cmd = SBIC_CMD_MSG_ACPT; - sbic_wait(regs, SBIC_CSR_INT); - c = regs->sbic_intr; - - regs->sbic_cmd = SBIC_CMD_XFER_INFO; - sbic_wait(regs, SBIC_CSR_INT); - c = regs->sbic_intr;/*ack*/ - c = regs->sbic_fifo; - - if (i == 1) tgt->sync_period = scsi_period_to_sbic(regs,c); - if (i == 2) tgt->sync_offset = c; - } - -cmd: - regs->sbic_cmd = SBIC_CMD_MSG_ACPT; - csr = sbic_wait(regs, SBIC_CSR_INT); - c = regs->sbic_intr; - - /* phase should normally be command here */ - if (SCSI_PHASE(csr) == SCSI_PHASE_CMD) { - /* test unit ready or what ? */ - regs->sbic_fifo = 0; - regs->sbic_fifo = 0; - regs->sbic_fifo = 0; - regs->sbic_fifo = 0; - regs->sbic_fifo = 0; - regs->sbic_fifo = 0; - SBIC_TC_PUT(regs,0xff); - regs->sbic_cmd = SBIC_CMD_XFER_PAD; /*0x98*/ - csr = sbic_wait(regs, SBIC_CSR_INT); - ir = regs->sbic_intr;/*ack*/ - } - -status: - if (SCSI_PHASE(csr) != SCSI_PHASE_STATUS) - gimmeabreak(); - -#endif - return TRUE; -} - -/* - * The bus was reset - */ -sbic_bus_reset(sbic) - register sbic_softc_t sbic; -{ - register sbic_padded_regmap_t *regs = sbic->regs; - - LOG(0x1d,"bus_reset"); - - /* - * Clear bus descriptor - */ - sbic->script = 0; - sbic->error_handler = 0; - sbic->active_target = 0; - sbic->next_target = 0; - sbic->state &= SBIC_STATE_AM_MODE; /* save this one bit only */ - queue_init(&sbic->waiting_targets); - sbic->wd.nactive = 0; - (void) sbic_reset(regs, TRUE); - - printf("sbic: (%d) bus reset ", ++sbic->wd.reset_count); - delay(scsi_delay_after_reset); /* some targets take long to reset */ - - if (sbic->sc == 0) /* sanity */ - return; - - scsi_bus_was_reset(sbic->sc); -} - -/* - * Disconnect/reconnect mode ops - */ - -/* save all relevant data, free the BUS */ -boolean_t -sbic_disconnected(sbic, csr, pha) - register sbic_softc_t sbic; - register unsigned char csr, pha; - -{ - register target_info_t *tgt; - - LOG(0x11,"disconnected"); - - tgt = sbic->active_target; - tgt->flags |= TGT_DISCONNECTED; - tgt->transient_state.handler = sbic->error_handler; - /* anything else was saved in sbic_err_disconn() */ - - PRINT(("{D%d}", tgt->target_id)); - - sbic_release_bus(sbic); - - return FALSE; -} - -/* See who reconnected, restore BUS */ -boolean_t -sbic_reconnect(sbic, csr, ir) - register sbic_softc_t sbic; - register unsigned char csr, ir; - -{ - register target_info_t *tgt; - sbic_padded_regmap_t *regs; - int id, pha; - - LOG(0x12,"reconnect"); - /* - * See if this reconnection collided with a selection attempt - */ - if (sbic->state & SBIC_STATE_BUSY) - sbic->state |= SBIC_STATE_COLLISION; - - sbic->state |= SBIC_STATE_BUSY; - - /* find tgt */ - regs = sbic->regs; - GET_SBIC_rselid(regs,id); - - id &= 0x7; - - if ((sbic->state & SBIC_STATE_AM) == 0) { - /* Must pick the identify */ - pha = 0x44; - } else - pha = 0x45; - - tgt = sbic->sc->target[id]; - if (id > 7 || tgt == 0) panic("sbic_reconnect"); - - /* synch things*/ - SET_SBIC_syn(regs,SBIC_SYN(tgt->sync_offset,tgt->sync_period)); - - PRINT(("{R%d}", id)); - if (sbic->state & SBIC_STATE_COLLISION) - PRINT(("[B %d-%d]", sbic->active_target->target_id, id)); - - LOG(0x80+id,0); - - sbic->active_target = tgt; - tgt->flags &= ~TGT_DISCONNECTED; - - sbic->script = tgt->transient_state.script; - sbic->error_handler = tgt->transient_state.handler; - sbic->in_count = 0; - sbic->out_count = 0; - -set counter and setup dma, then - - /* Resume the command now */ - SET_SBIC_cmd_phase(regs, pha); - SET_SBIC_cmd(regs, SBIC_CMD_SEL_XFER); - - return FALSE; -} - -TILL HERE - -/* - * Error handlers - */ - -/* - * Fall-back error handler. - */ -sbic_err_generic(sbic, csr, ir) - register sbic_softc_t sbic; -{ - LOG(0x13,"err_generic"); - - /* handle non-existant or powered off devices here */ - if ((ir == SBIC_INT_DISC) && - (sbic_isa_select(sbic->cmd_was)) && - (SBIC_SS(sbic->ss_was) == 0)) { - /* Powered off ? */ - if (sbic->active_target->flags & TGT_FULLY_PROBED) - sbic->active_target->flags = 0; - sbic->done = SCSI_RET_DEVICE_DOWN; - sbic_end(sbic, csr, ir); - return; - } - - switch (SCSI_PHASE(csr)) { - case SCSI_PHASE_STATUS: - if (sbic->script[-1].condition == SCSI_PHASE_STATUS) { - /* some are just slow to get out.. */ - } else - sbic_err_to_status(sbic, csr, ir); - return; - break; - case SCSI_PHASE_DATAI: - if (sbic->script->condition == SCSI_PHASE_STATUS) { -/* printf("{P}");*/ - return; - } - break; - case SCSI_PHASE_DATAO: - if (sbic->script->condition == SCSI_PHASE_STATUS) { - /* - * See comment above. Actually seen on hitachis. - */ -/* printf("{P}");*/ - return; - } - } - gimmeabreak(); -} - -/* - * Handle disconnections as exceptions - */ -sbic_err_disconn(sbic, csr, ir) - register sbic_softc_t sbic; - register unsigned char csr, ir; -{ - register sbic_padded_regmap_t *regs; - register target_info_t *tgt; - int count; - boolean_t callback = FALSE; - - LOG(0x16,"err_disconn"); - - if (SCSI_PHASE(csr) != SCSI_PHASE_MSG_IN) - return sbic_err_generic(sbic, csr, ir); - - regs = sbic->regs; - tgt = sbic->active_target; - - switch (sbic->script->condition) { - case SCSI_PHASE_DATAO: - LOG(0x1b,"+DATAO"); - if (sbic->out_count) { - register int xferred, offset; - - SBIC_TC_GET(regs,xferred); /* temporary misnomer */ - xferred += regs->sbic_flags & SBIC_FLAGS_FIFO_CNT; - xferred -= sbic->extra_count; - xferred = sbic->out_count - xferred; /* ok now */ - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - - callback = (*sbic->dma_ops->disconn_1) - (sbic->dma_state, tgt, xferred); - - } else { - - callback = (*sbic->dma_ops->disconn_2) - (sbic->dma_state, tgt); - - } - sbic->extra_count = 0; - tgt->transient_state.script = sbic_script_restart_data_out; - break; - - - case SCSI_PHASE_DATAI: - LOG(0x17,"+DATAI"); - if (sbic->in_count) { - register int offset, xferred; - - SBIC_TC_GET(regs,count); - xferred = sbic->in_count - count; - assert(xferred > 0); - -if (regs->sbic_flags & 0xf) -printf("{Xf %x,%x,%x}", xferred, sbic->in_count, regs->sbic_flags & SBIC_FLAGS_FIFO_CNT); - tgt->transient_state.in_count -= xferred; - assert(tgt->transient_state.in_count > 0); - - callback = (*sbic->dma_ops->disconn_3) - (sbic->dma_state, tgt, xferred); - - tgt->transient_state.script = sbic_script_restart_data_in; - if (tgt->transient_state.in_count == 0) - tgt->transient_state.script++; - - } - tgt->transient_state.script = sbic->script; - break; - - case SCSI_PHASE_STATUS: - /* will have to restart dma */ - SBIC_TC_GET(regs,count); - if (sbic->state & SBIC_STATE_DMA_IN) { - register int offset, xferred; - - LOG(0x1a,"+STATUS+R"); - - xferred = sbic->in_count - count; - assert(xferred > 0); - -if (regs->sbic_flags & 0xf) -printf("{Xf %x,%x,%x}", xferred, sbic->in_count, regs->sbic_flags & SBIC_FLAGS_FIFO_CNT); - tgt->transient_state.in_count -= xferred; -/* assert(tgt->transient_state.in_count > 0);*/ - - callback = (*sbic->dma_ops->disconn_4) - (sbic->dma_state, tgt, xferred); - - tgt->transient_state.script = sbic_script_restart_data_in; - if (tgt->transient_state.in_count == 0) - tgt->transient_state.script++; - - } else { - - /* add what's left in the fifo */ - count += (regs->sbic_flags & SBIC_FLAGS_FIFO_CNT); - /* take back the extra we might have added */ - count -= sbic->extra_count; - /* ..and drop that idea */ - sbic->extra_count = 0; - - LOG(0x19,"+STATUS+W"); - - - if ((count == 0) && (tgt->transient_state.out_count == sbic->out_count)) { - /* all done */ - tgt->transient_state.script = sbic->script; - tgt->transient_state.out_count = 0; - } else { - register int xferred, offset; - - /* how much we xferred */ - xferred = sbic->out_count - count; - - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - - callback = (*sbic->dma_ops->disconn_5) - (sbic->dma_state,tgt,xferred); - - tgt->transient_state.script = sbic_script_restart_data_out; - } - sbic->out_count = 0; - } - break; - default: - gimmeabreak(); - return; - } - sbic_msg_in(sbic,csr,ir); - sbic->script = sbic_script_disconnect; - regs->sbic_cmd = SBIC_CMD_XFER_INFO|SBIC_CMD_DMA; - if (callback) - (*sbic->dma_ops->disconn_callback)(sbic->dma_state, tgt); -} - -/* - * Watchdog - * - * We know that some (name withdrawn) disks get - * stuck in the middle of dma phases... - */ -sbic_reset_scsibus(sbic) - register sbic_softc_t sbic; -{ - register target_info_t *tgt = sbic->active_target; - register sbic_padded_regmap_t *regs = sbic->regs; - register int ir; - - if (scsi_debug && tgt) { - int dmalen; - SBIC_TC_GET(sbic->regs,dmalen); - printf("Target %d was active, cmd x%x in x%x out x%x Sin x%x Sou x%x dmalen x%x\n", - tgt->target_id, tgt->cur_cmd, - tgt->transient_state.in_count, tgt->transient_state.out_count, - sbic->in_count, sbic->out_count, - dmalen); - } - ir = regs->sbic_intr; - if ((ir & SBIC_INT_RESEL) && (SCSI_PHASE(regs->sbic_csr) == SCSI_PHASE_MSG_IN)) { - /* getting it out of the woods is a bit tricky */ - spl_t s = splbio(); - - (void) sbic_reconnect(sbic, regs->sbic_csr, ir); - sbic_wait(regs, SBIC_CSR_INT); - ir = regs->sbic_intr; - regs->sbic_cmd = SBIC_CMD_MSG_ACPT; - splx(s); - } else { - regs->sbic_cmd = SBIC_CMD_BUS_RESET; - delay(35); - } -} - -#endif NSBIC > 0 - -#endif 0 diff --git a/scsi/adapters/scsi_5380.h b/scsi/adapters/scsi_5380.h deleted file mode 100644 index 12be922..0000000 --- a/scsi/adapters/scsi_5380.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ -/* - * File: scsi_5380.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 5/91 - * - * Defines for the NCR 5380 (SCSI chip), aka Am5380 - */ - -/* - * Register map - */ - -typedef struct { - volatile unsigned char sci_data; /* r: Current data */ -#define sci_odata sci_data /* w: Out data */ - volatile unsigned char sci_icmd; /* rw: Initiator command */ - volatile unsigned char sci_mode; /* rw: Mode */ - volatile unsigned char sci_tcmd; /* rw: Target command */ - volatile unsigned char sci_bus_csr; /* r: Bus Status */ -#define sci_sel_enb sci_bus_csr /* w: Select enable */ - volatile unsigned char sci_csr; /* r: Status */ -#define sci_dma_send sci_csr /* w: Start dma send data */ - volatile unsigned char sci_idata; /* r: Input data */ -#define sci_trecv sci_idata /* w: Start dma receive, target */ - volatile unsigned char sci_iack; /* r: Interrupt Acknowledge */ -#define sci_irecv sci_iack /* w: Start dma receive, initiator */ -} sci_regmap_t; - - -/* - * Initiator command register - */ - -#define SCI_ICMD_DATA 0x01 /* rw: Assert data bus */ -#define SCI_ICMD_ATN 0x02 /* rw: Assert ATN signal */ -#define SCI_ICMD_SEL 0x04 /* rw: Assert SEL signal */ -#define SCI_ICMD_BSY 0x08 /* rw: Assert BSY signal */ -#define SCI_ICMD_ACK 0x10 /* rw: Assert ACK signal */ -#define SCI_ICMD_LST 0x20 /* r: Lost arbitration */ -#define SCI_ICMD_DIFF SCI_ICMD_LST /* w: Differential cable */ -#define SCI_ICMD_AIP 0x40 /* r: Arbitration in progress */ -#define SCI_ICMD_TEST SCI_ICMD_AIP /* w: Test mode */ -#define SCI_ICMD_RST 0x80 /* rw: Assert RST signal */ - - -/* - * Mode register - */ - -#define SCI_MODE_ARB 0x01 /* rw: Start arbitration */ -#define SCI_MODE_DMA 0x02 /* rw: Enable DMA xfers */ -#define SCI_MODE_MONBSY 0x04 /* rw: Monitor BSY signal */ -#define SCI_MODE_DMA_IE 0x08 /* rw: Enable DMA complete interrupt */ -#define SCI_MODE_PERR_IE 0x10 /* rw: Interrupt on parity errors */ -#define SCI_MODE_PAR_CHK 0x20 /* rw: Check parity */ -#define SCI_MODE_TARGET 0x40 /* rw: Target mode (Initiator if 0) */ -#define SCI_MODE_BLOCKDMA 0x80 /* rw: Block-mode DMA handshake (MBZ) */ - - -/* - * Target command register - */ - -#define SCI_TCMD_IO 0x01 /* rw: Assert I/O signal */ -#define SCI_TCMD_CD 0x02 /* rw: Assert C/D signal */ -#define SCI_TCMD_MSG 0x04 /* rw: Assert MSG signal */ -#define SCI_TCMD_PHASE_MASK 0x07 /* r: Mask for current bus phase */ -#define SCI_TCMD_REQ 0x08 /* rw: Assert REQ signal */ -#define SCI_TCMD_LAST_SENT 0x80 /* ro: Last byte was xferred - * (not on 5380/1) */ - -#define SCI_PHASE(x) SCSI_PHASE(x) - -/* - * Current (SCSI) Bus status - */ - -#define SCI_BUS_DBP 0x01 /* r: Data Bus parity */ -#define SCI_BUS_SEL 0x02 /* r: SEL signal */ -#define SCI_BUS_IO 0x04 /* r: I/O signal */ -#define SCI_BUS_CD 0x08 /* r: C/D signal */ -#define SCI_BUS_MSG 0x10 /* r: MSG signal */ -#define SCI_BUS_REQ 0x20 /* r: REQ signal */ -#define SCI_BUS_BSY 0x40 /* r: BSY signal */ -#define SCI_BUS_RST 0x80 /* r: RST signal */ - -#define SCI_CUR_PHASE(x) SCSI_PHASE((x)>>2) - -/* - * Bus and Status register - */ - -#define SCI_CSR_ACK 0x01 /* r: ACK signal */ -#define SCI_CSR_ATN 0x02 /* r: ATN signal */ -#define SCI_CSR_DISC 0x04 /* r: Disconnected (BSY==0) */ -#define SCI_CSR_PHASE_MATCH 0x08 /* r: Bus and SCI_TCMD match */ -#define SCI_CSR_INT 0x10 /* r: Interrupt request */ -#define SCI_CSR_PERR 0x20 /* r: Parity error */ -#define SCI_CSR_DREQ 0x40 /* r: DMA request */ -#define SCI_CSR_DONE 0x80 /* r: DMA count is zero */ - diff --git a/scsi/adapters/scsi_5380_hdw.c b/scsi/adapters/scsi_5380_hdw.c deleted file mode 100644 index 2fc7d89..0000000 --- a/scsi/adapters/scsi_5380_hdw.c +++ /dev/null @@ -1,2423 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ -/* - * File: scsi_5380_hdw.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 4/91 - * - * Bottom layer of the SCSI driver: chip-dependent functions - * - * This file contains the code that is specific to the NCR 5380 - * SCSI chip (Host Bus Adapter in SCSI parlance): probing, start - * operation, and interrupt routine. - */ - -/* - * This layer works based on small simple 'scripts' that are installed - * at the start of the command and drive the chip to completion. - * The idea comes from the specs of the NCR 53C700 'script' processor. - * - * There are various reasons for this, mainly - * - Performance: identify the common (successful) path, and follow it; - * at interrupt time no code is needed to find the current status - * - Code size: it should be easy to compact common operations - * - Adaptability: the code skeleton should adapt to different chips without - * terrible complications. - * - Error handling: and it is easy to modify the actions performed - * by the scripts to cope with strange but well identified sequences - * - */ - -#include <sci.h> -#if NSCI > 0 -#include <platforms.h> - -#include <mach/std_types.h> -#include <sys/types.h> -#include <chips/busses.h> -#include <scsi/compat_30.h> -#include <machine/machspl.h> - -#include <sys/syslog.h> - -#include <scsi/scsi.h> -#include <scsi/scsi2.h> -#include <scsi/scsi_defs.h> - -#ifdef VAXSTATION -#define PAD(n) char n[3] -#endif - -#include <scsi/adapters/scsi_5380.h> - -#ifdef PAD -typedef struct { - volatile unsigned char sci_data; /* r: Current data */ -/*#define sci_odata sci_data /* w: Out data */ - PAD(pad0); - - volatile unsigned char sci_icmd; /* rw: Initiator command */ - PAD(pad1); - - volatile unsigned char sci_mode; /* rw: Mode */ - PAD(pad2); - - volatile unsigned char sci_tcmd; /* rw: Target command */ - PAD(pad3); - - volatile unsigned char sci_bus_csr; /* r: Bus Status */ -/*#define sci_sel_enb sci_bus_csr /* w: Select enable */ - PAD(pad4); - - volatile unsigned char sci_csr; /* r: Status */ -/*#define sci_dma_send sci_csr /* w: Start dma send data */ - PAD(pad5); - - volatile unsigned char sci_idata; /* r: Input data */ -/*#define sci_trecv sci_idata /* w: Start dma receive, target */ - PAD(pad6); - - volatile unsigned char sci_iack; /* r: Interrupt Acknowledge */ -/*#define sci_irecv sci_iack /* w: Start dma receive, initiator */ - PAD(pad7); - -} sci_padded_regmap_t; -#else -typedef sci_regmap_t sci_padded_regmap_t; -#endif - -#ifdef VAXSTATION -#define check_memory(addr,dow) ((dow) ? wbadaddr(addr,4) : badaddr(addr,4)) - -/* vax3100 */ -#include <chips/vs42x_rb.h> -#define STC_5380_A VAX3100_STC_5380_A -#define STC_5380_B VAX3100_STC_5380_B -#define STC_DMAREG_OFF VAX3100_STC_DMAREG_OFF - -static int mem; /* mem++ seems to take approx 0.34 usecs */ -#define delay_1p2_us() {mem++;mem++;mem++;mem++;} -#define my_scsi_id(ctlr) (ka3100_scsi_id((ctlr))) -#endif /* VAXSTATION */ - - -#ifndef STC_5380_A /* cross compile check */ -typedef struct { - int sci_dma_dir, sci_dma_adr; -} *sci_dmaregs_t; -#define STC_DMAREG_OFF 0 -#define SCI_DMA_DIR_WRITE 0 -#define SCI_DMA_DIR_READ 1 -#define STC_5380_A 0 -#define STC_5380_B 0x100 -#define SCI_RAM_SIZE 0x10000 -#endif - -/* - * The 5380 can't tell you the scsi ID it uses, so - * unless there is another way use the defaults - */ -#ifndef my_scsi_id -#define my_scsi_id(ctlr) (scsi_initiator_id[(ctlr)]) -#endif - -/* - * Statically partition the DMA buffer between targets. - * This way we will eventually be able to attach/detach - * drives on-fly. And 18k/target is enough. - */ -#define PER_TGT_DMA_SIZE ((SCI_RAM_SIZE/7) & ~(sizeof(int)-1)) - -/* - * Round to 4k to make debug easier - */ -#define PER_TGT_BUFF_SIZE ((PER_TGT_DMA_SIZE >> 12) << 12) -#define PER_TGT_BURST_SIZE (PER_TGT_BUFF_SIZE>>1) - -/* - * Macros to make certain things a little more readable - */ - -#define SCI_ACK(ptr,phase) (ptr)->sci_tcmd = (phase) -#define SCI_CLR_INTR(regs) {register int temp = regs->sci_iack;} - - -/* - * A script has a two parts: a pre-condition and an action. - * The first triggers error handling if not satisfied and in - * our case it is formed by the current bus phase and connected - * condition as per bus status bits. The action part is just a - * function pointer, invoked in a standard way. The script - * pointer is advanced only if the action routine returns TRUE. - * See sci_intr() for how and where this is all done. - */ - -typedef struct script { - int condition; /* expected state at interrupt */ - int (*action)(); /* action routine */ -} *script_t; - -#define SCRIPT_MATCH(cs,bs) (((bs)&SCI_BUS_BSY)|SCI_CUR_PHASE((bs))) - -#define SCI_PHASE_DISC 0x0 /* sort of .. */ - - -/* forward decls of script actions */ -boolean_t - sci_dosynch(), /* negotiate synch xfer */ - sci_dma_in(), /* get data from target via dma */ - sci_dma_out(), /* send data to target via dma */ - sci_get_status(), /* get status from target */ - sci_end_transaction(), /* all come to an end */ - sci_msg_in(), /* get disconnect message(s) */ - sci_disconnected(); /* current target disconnected */ -/* forward decls of error handlers */ -boolean_t - sci_err_generic(), /* generic error handler */ - sci_err_disconn(), /* when a target disconnects */ - gimmeabreak(); /* drop into the debugger */ - -int sci_reset_scsibus(); -boolean_t sci_probe_target(); - -scsi_ret_t sci_select_target(); - -#ifdef VAXSTATION -/* - * This should be somewhere else, and it was a - * mistake to share this buffer across SCSIs. - */ -struct dmabuffer { - volatile char *base; - char *sbrk; -} dmab[1]; - -volatile char * -sci_buffer_base(unit) -{ - return dmab[unit].base; -} - -sci_buffer_init(dmar, ram) - sci_dmaregs_t dmar; - volatile char *ram; -{ - dmar->sci_dma_rammode = SCI_RAM_EXPMODE; - dmab[0].base = dmab[0].sbrk = (char *) ram; - blkclr((char *) ram, SCI_RAM_SIZE); -} -char * -sci_buffer_sbrk(size) -{ - char *ret = dmab[0].sbrk; - - dmab[0].sbrk += size; - if ((dmab[0].sbrk - dmab[0].base) > SCI_RAM_SIZE) - panic("scialloc"); - return ret; -} - -#endif /* VAXSTATION */ - -/* - * State descriptor for this layer. There is one such structure - * per (enabled) 5380 interface - */ -struct sci_softc { - watchdog_t wd; - sci_padded_regmap_t *regs; /* 5380 registers */ - sci_dmaregs_t dmar; /* DMA controller registers */ - volatile char *buff; /* DMA buffer memory (I/O space) */ - script_t script; - int (*error_handler)(); - int in_count; /* amnt we expect to receive */ - int out_count; /* amnt we are going to ship */ - - volatile char state; -#define SCI_STATE_BUSY 0x01 /* selecting or currently connected */ -#define SCI_STATE_TARGET 0x04 /* currently selected as target */ -#define SCI_STATE_COLLISION 0x08 /* lost selection attempt */ -#define SCI_STATE_DMA_IN 0x10 /* tgt --> initiator xfer */ - - unsigned char ntargets; /* how many alive on this scsibus */ - unsigned char done; - unsigned char extra_byte; - - scsi_softc_t *sc; - target_info_t *active_target; - - target_info_t *next_target; /* trying to seize bus */ - queue_head_t waiting_targets;/* other targets competing for bus */ - -} sci_softc_data[NSCI]; - -typedef struct sci_softc *sci_softc_t; - -sci_softc_t sci_softc[NSCI]; - -/* - * Definition of the controller for the auto-configuration program. - */ - -int sci_probe(), scsi_slave(), sci_go(), sci_intr(); -void scsi_attach(); - -vm_offset_t sci_std[NSCI] = { 0 }; -struct bus_device *sci_dinfo[NSCI*8]; -struct bus_ctlr *sci_minfo[NSCI]; -struct bus_driver sci_driver = - { sci_probe, scsi_slave, scsi_attach, sci_go, sci_std, "rz", sci_dinfo, - "sci", sci_minfo, BUS_INTR_B4_PROBE}; - -/* - * Scripts - */ -struct script -sci_script_data_in[] = { - { SCSI_PHASE_DATAI|SCI_BUS_BSY, sci_dma_in}, - { SCSI_PHASE_STATUS|SCI_BUS_BSY, sci_get_status}, - { SCSI_PHASE_MSG_IN|SCI_BUS_BSY, sci_end_transaction} -}, - -sci_script_data_out[] = { - { SCSI_PHASE_DATAO|SCI_BUS_BSY, sci_dma_out}, - { SCSI_PHASE_STATUS|SCI_BUS_BSY, sci_get_status}, - { SCSI_PHASE_MSG_IN|SCI_BUS_BSY, sci_end_transaction} -}, - -sci_script_cmd[] = { - { SCSI_PHASE_STATUS|SCI_BUS_BSY, sci_get_status}, - { SCSI_PHASE_MSG_IN|SCI_BUS_BSY, sci_end_transaction} -}, - -/* Synchronous transfer neg(oti)ation */ - -sci_script_try_synch[] = { - { SCSI_PHASE_MSG_OUT|SCI_BUS_BSY, sci_dosynch} -}, - -/* Disconnect sequence */ - -sci_script_disconnect[] = { - { SCI_PHASE_DISC, sci_disconnected} -}; - - - -#define u_min(a,b) (((a) < (b)) ? (a) : (b)) - - -#define DEBUG -#ifdef DEBUG - -sci_state(base) - vm_offset_t base; -{ - sci_padded_regmap_t *regs; - sci_dmaregs_t dmar; - extern char *sci; - unsigned dmadr; - int cnt, i; - - if (base == 0) - base = (vm_offset_t)sci; - - for (i = 0; i < 2; i++) { - regs = (sci_padded_regmap_t*) (base + - (i ? STC_5380_B : STC_5380_A)); - dmar = (sci_dmaregs_t) ((char*)regs + STC_DMAREG_OFF); - SCI_DMADR_GET(dmar,dmadr); - SCI_TC_GET(dmar,cnt); - - db_printf("scsi%d: ph %x (sb %x), mode %x, tph %x, csr %x, cmd %x, ", - i, - (unsigned) SCI_CUR_PHASE(regs->sci_bus_csr), - (unsigned) regs->sci_bus_csr, - (unsigned) regs->sci_mode, - (unsigned) regs->sci_tcmd, - (unsigned) regs->sci_csr, - (unsigned) regs->sci_icmd); - db_printf("dma%c %x @ %x\n", - (dmar->sci_dma_dir) ? 'I' : 'O', cnt, dmadr); - } - return 0; -} -sci_target_state(tgt) - target_info_t *tgt; -{ - if (tgt == 0) - tgt = sci_softc[0]->active_target; - if (tgt == 0) - return 0; - db_printf("fl %x dma %x+%x cmd %x id %x per %x off %x ior %x ret %x\n", - tgt->flags, tgt->dma_ptr, tgt->transient_state.dma_offset, - tgt->cmd_ptr, tgt->target_id, tgt->sync_period, tgt->sync_offset, - tgt->ior, tgt->done); - if (tgt->flags & TGT_DISCONNECTED){ - script_t spt; - - spt = tgt->transient_state.script; - db_printf("disconnected at "); - db_printsym(spt,1); - db_printf(": %x ", spt->condition); - db_printsym(spt->action,1); - db_printf(", "); - db_printsym(tgt->transient_state.handler, 1); - db_printf("\n"); - } - - return 0; -} - -sci_all_targets(unit) -{ - int i; - target_info_t *tgt; - for (i = 0; i < 8; i++) { - tgt = sci_softc[unit]->sc->target[i]; - if (tgt) - sci_target_state(tgt); - } -} - -sci_script_state(unit) -{ - script_t spt = sci_softc[unit]->script; - - if (spt == 0) return 0; - db_printsym(spt,1); - db_printf(": %x ", spt->condition); - db_printsym(spt->action,1); - db_printf(", "); - db_printsym(sci_softc[unit]->error_handler, 1); - return 0; - -} - -#define PRINT(x) if (scsi_debug) printf x - -#define TRMAX 200 -int tr[TRMAX+3]; -int trpt, trpthi; -#define TR(x) tr[trpt++] = x -#define TRWRAP trpthi = trpt; trpt = 0; -#define TRCHECK if (trpt > TRMAX) {TRWRAP} - -#define TRACE - -#ifdef TRACE - -#define LOGSIZE 256 -int sci_logpt; -char sci_log[LOGSIZE]; - -#define MAXLOG_VALUE 0x24 -struct { - char *name; - unsigned int count; -} logtbl[MAXLOG_VALUE]; - -static LOG(e,f) - char *f; -{ - sci_log[sci_logpt++] = (e); - if (sci_logpt == LOGSIZE) sci_logpt = 0; - if ((e) < MAXLOG_VALUE) { - logtbl[(e)].name = (f); - logtbl[(e)].count++; - } -} - -sci_print_log(skip) - int skip; -{ - register int i, j; - register unsigned char c; - - for (i = 0, j = sci_logpt; i < LOGSIZE; i++) { - c = sci_log[j]; - if (++j == LOGSIZE) j = 0; - if (skip-- > 0) - continue; - if (c < MAXLOG_VALUE) - db_printf(" %s", logtbl[c].name); - else - db_printf("-%d", c & 0x7f); - } - db_printf("\n"); - return 0; -} - -sci_print_stat() -{ - register int i; - register char *p; - for (i = 0; i < MAXLOG_VALUE; i++) { - if (p = logtbl[i].name) - printf("%d %s\n", logtbl[i].count, p); - } -} - -#else /* TRACE */ -#define LOG(e,f) -#endif /* TRACE */ - -#else /* DEBUG */ -#define PRINT(x) -#define LOG(e,f) -#define TR(x) -#define TRCHECK -#define TRWRAP -#endif /* DEBUG */ - - -/* - * Probe/Slave/Attach functions - */ - -/* - * Probe routine: - * Should find out (a) if the controller is - * present and (b) which/where slaves are present. - * - * Implementation: - * Send an identify msg to each possible target on the bus - * except of course ourselves. - */ -sci_probe(reg, ui) - char *reg; - struct bus_ctlr *ui; -{ - int unit = ui->unit; - sci_softc_t sci = &sci_softc_data[unit]; - int target_id, i; - scsi_softc_t *sc; - register sci_padded_regmap_t *regs; - spl_t s; - boolean_t did_banner = FALSE; - char *cmd_ptr; - static char *here = "sci_probe"; - - /* - * We are only called if the chip is there, - * but make sure anyways.. - */ - regs = (sci_padded_regmap_t *) (reg); - if (check_memory(regs, 0)) - return 0; - -#if notyet - /* Mappable version side */ - SCI_probe(reg, ui); -#endif - - /* - * Initialize hw descriptor - */ - sci_softc[unit] = sci; - sci->regs = regs; - sci->dmar = (sci_dmaregs_t)(reg + STC_DMAREG_OFF); - sci->buff = sci_buffer_base(0); - - queue_init(&sci->waiting_targets); - - sc = scsi_master_alloc(unit, sci); - sci->sc = sc; - - sc->go = sci_go; - sc->probe = sci_probe_target; - sc->watchdog = scsi_watchdog; - sci->wd.reset = sci_reset_scsibus; - -#ifdef MACH_KERNEL - sc->max_dma_data = -1; /* unlimited */ -#else - sc->max_dma_data = scsi_per_target_virtual; -#endif - - scsi_might_disconnect[unit] = 0; /* still true */ - - /* - * Reset chip - */ - s = splbio(); - sci_reset(sci, TRUE); - SCI_CLR_INTR(regs); - - /* - * Our SCSI id on the bus. - */ - - sc->initiator_id = my_scsi_id(unit); - printf("%s%d: my SCSI id is %d", ui->name, unit, sc->initiator_id); - - /* - * For all possible targets, see if there is one and allocate - * a descriptor for it if it is there. - */ - cmd_ptr = sci_buffer_sbrk(0); - for (target_id = 0; target_id < 8; target_id++) { - - register unsigned csr, dsr; - scsi_status_byte_t status; - - /* except of course ourselves */ - if (target_id == sc->initiator_id) - continue; - - if (sci_select_target( regs, sc->initiator_id, target_id, FALSE) == SCSI_RET_DEVICE_DOWN) { - SCI_CLR_INTR(regs); - continue; - } - - printf(",%s%d", did_banner++ ? " " : " target(s) at ", - target_id); - - /* should be command phase here: we selected wo ATN! */ - while (SCI_CUR_PHASE(regs->sci_bus_csr) != SCSI_PHASE_CMD) - ; - - SCI_ACK(regs,SCSI_PHASE_CMD); - - /* build command in dma area */ - { - unsigned char *p = (unsigned char*) cmd_ptr; - - p[0] = SCSI_CMD_TEST_UNIT_READY; - p[1] = - p[2] = - p[3] = - p[4] = - p[5] = 0; - } - - sci_data_out(regs, SCSI_PHASE_CMD, 6, cmd_ptr); - - while (SCI_CUR_PHASE(regs->sci_bus_csr) != SCSI_PHASE_STATUS) - ; - - SCI_ACK(regs,SCSI_PHASE_STATUS); - - sci_data_in(regs, SCSI_PHASE_STATUS, 1, &status.bits); - - if (status.st.scsi_status_code != SCSI_ST_GOOD) - scsi_error( 0, SCSI_ERR_STATUS, status.bits, 0); - - /* get cmd_complete message */ - while (SCI_CUR_PHASE(regs->sci_bus_csr) != SCSI_PHASE_MSG_IN) - ; - - SCI_ACK(regs,SCSI_PHASE_MSG_IN); - - sci_data_in(regs, SCSI_PHASE_MSG_IN, 1, &i); - - /* check disconnected, clear all intr bits */ - while (regs->sci_bus_csr & SCI_BUS_BSY) - ; - SCI_ACK(regs,SCI_PHASE_DISC); - - SCI_CLR_INTR(regs); - - /* ... */ - - /* - * Found a target - */ - sci->ntargets++; - { - register target_info_t *tgt; - - tgt = scsi_slave_alloc(unit, target_id, sci); - - /* "virtual" address for our use */ - tgt->cmd_ptr = sci_buffer_sbrk(PER_TGT_DMA_SIZE); - /* "physical" address for dma engine */ - tgt->dma_ptr = (char*)(tgt->cmd_ptr - sci->buff); -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - fdma_init(&tgt->fdma, scsi_per_target_virtual); -#endif /*MACH_KERNEL*/ - } - } - printf(".\n"); - - splx(s); - return 1; -} - -boolean_t -sci_probe_target(tgt, ior) - target_info_t *tgt; - io_req_t ior; -{ - sci_softc_t sci = sci_softc[tgt->masterno]; - boolean_t newlywed; - - newlywed = (tgt->cmd_ptr == 0); - if (newlywed) { - /* desc was allocated afresh */ - - /* "virtual" address for our use */ - tgt->cmd_ptr = sci_buffer_sbrk(PER_TGT_DMA_SIZE); - /* "physical" address for dma engine */ - tgt->dma_ptr = (char*)(tgt->cmd_ptr - sci->buff); -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - fdma_init(&tgt->fdma, scsi_per_target_virtual); -#endif /*MACH_KERNEL*/ - - } - - if (scsi_inquiry(tgt, SCSI_INQ_STD_DATA) == SCSI_RET_DEVICE_DOWN) - return FALSE; - - tgt->flags = TGT_ALIVE; - return TRUE; -} - - -static sci_wait(preg, until) - volatile unsigned char *preg; -{ - int timeo = 1000000; - /* read it over to avoid bus glitches */ - while ( ((*preg & until) != until) || - ((*preg & until) != until) || - ((*preg & until) != until)) { - delay(1); - if (!timeo--) { - printf("sci_wait TIMEO with x%x\n", *preg); - break; - } - } - return *preg; -} - -scsi_ret_t -sci_select_target(regs, myid, id, with_atn) - register sci_padded_regmap_t *regs; - unsigned char myid, id; - boolean_t with_atn; -{ - register unsigned char bid, icmd; - scsi_ret_t ret = SCSI_RET_RETRY; - - if ((regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && - (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && - (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL))) - return ret; - - /* for our purposes.. */ - myid = 1 << myid; - id = 1 << id; - - regs->sci_sel_enb = myid; /* if not there already */ - - regs->sci_odata = myid; - regs->sci_mode |= SCI_MODE_ARB; - /* AIP might not set if BSY went true after we checked */ - for (bid = 0; bid < 20; bid++) /* 20usec circa */ - if (regs->sci_icmd & SCI_ICMD_AIP) - break; - if ((regs->sci_icmd & SCI_ICMD_AIP) == 0) { - goto lost; - } - - delay(2); /* 2.2us arb delay */ - - if (regs->sci_icmd & SCI_ICMD_LST) { - goto lost; - } - - regs->sci_mode &= ~SCI_MODE_PAR_CHK; - bid = regs->sci_data; - - if ((bid & ~myid) > myid) { - goto lost; - } - if (regs->sci_icmd & SCI_ICMD_LST) { - goto lost; - } - - /* Won arbitration, enter selection phase now */ - icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); - icmd |= (with_atn ? (SCI_ICMD_SEL|SCI_ICMD_ATN) : SCI_ICMD_SEL); - regs->sci_icmd = icmd; - - if (regs->sci_icmd & SCI_ICMD_LST) { - goto nosel; - } - - /* XXX a target that violates specs might still drive the bus XXX */ - /* XXX should put our id out, and after the delay check nothi XXX */ - /* XXX ng else is out there. XXX */ - - delay_1p2_us(); - - regs->sci_sel_enb = 0; - - regs->sci_odata = myid | id; - - icmd |= SCI_ICMD_BSY|SCI_ICMD_DATA; - regs->sci_icmd = icmd; - - regs->sci_mode &= ~SCI_MODE_ARB; /* 2 deskew delays, too */ - - icmd &= ~SCI_ICMD_BSY; - regs->sci_icmd = icmd; - - /* bus settle delay, 400ns */ - delay(0); /* too much ? */ - - regs->sci_mode |= SCI_MODE_PAR_CHK; - - { - register int timeo = 2500;/* 250 msecs in 100 usecs chunks */ - while ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) - if (--timeo > 0) - delay(100); - else { - goto nodev; - } - } - - icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL); - regs->sci_icmd = icmd; -/* regs->sci_sel_enb = myid;*/ /* looks like we should NOT have it */ - return SCSI_RET_SUCCESS; -nodev: - ret = SCSI_RET_DEVICE_DOWN; - regs->sci_sel_enb = myid; -nosel: - icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL|SCI_ICMD_ATN); - regs->sci_icmd = icmd; -lost: - bid = regs->sci_mode; - bid &= ~SCI_MODE_ARB; - bid |= SCI_MODE_PAR_CHK; - regs->sci_mode = bid; - - return ret; -} - -sci_data_out(regs, phase, count, data) - register sci_padded_regmap_t *regs; - unsigned char *data; -{ - register unsigned char icmd; - - /* ..checks.. */ - - icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); -loop: - if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase) - return count; - - while ( ((regs->sci_bus_csr & SCI_BUS_REQ) == 0) && - ((regs->sci_bus_csr & SCI_BUS_REQ) == 0) && - ((regs->sci_bus_csr & SCI_BUS_REQ) == 0)) - ; - icmd |= SCI_ICMD_DATA; - regs->sci_icmd = icmd; - regs->sci_odata = *data++; - icmd |= SCI_ICMD_ACK; - regs->sci_icmd = icmd; - - icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_ACK); - while ( (regs->sci_bus_csr & SCI_BUS_REQ) && - (regs->sci_bus_csr & SCI_BUS_REQ) && - (regs->sci_bus_csr & SCI_BUS_REQ)) - ; - regs->sci_icmd = icmd; - if (--count > 0) - goto loop; - return 0; -} - -sci_data_in(regs, phase, count, data) - register sci_padded_regmap_t *regs; - unsigned char *data; -{ - register unsigned char icmd; - - /* ..checks.. */ - - icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); -loop: - if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase) - return count; - - while ( ((regs->sci_bus_csr & SCI_BUS_REQ) == 0) && - ((regs->sci_bus_csr & SCI_BUS_REQ) == 0) && - ((regs->sci_bus_csr & SCI_BUS_REQ) == 0)) - ; - *data++ = regs->sci_data; - icmd |= SCI_ICMD_ACK; - regs->sci_icmd = icmd; - - icmd &= ~SCI_ICMD_ACK; - while ( (regs->sci_bus_csr & SCI_BUS_REQ) && - (regs->sci_bus_csr & SCI_BUS_REQ) && - (regs->sci_bus_csr & SCI_BUS_REQ)) - ; - regs->sci_icmd = icmd; - if (--count > 0) - goto loop; - return 0; - -} - -sci_reset(sci, quickly) - sci_softc_t sci; - boolean_t quickly; -{ - register sci_padded_regmap_t *regs = sci->regs; - register sci_dmaregs_t dma = sci->dmar; - int dummy; - - regs->sci_icmd = SCI_ICMD_TEST; /* don't drive outputs */ - regs->sci_icmd = SCI_ICMD_TEST|SCI_ICMD_RST; - delay(25); - regs->sci_icmd = 0; - - regs->sci_mode = SCI_MODE_PAR_CHK|SCI_MODE_PERR_IE; - regs->sci_tcmd = SCI_PHASE_DISC; /* make sure we do not miss transition */ - regs->sci_sel_enb = 0; - - /* idle the dma controller */ - dma->sci_dma_adr = 0; - dma->sci_dma_dir = SCI_DMA_DIR_WRITE; - SCI_TC_PUT(dma,0); - - /* clear interrupt (two might be queued?) */ - SCI_CLR_INTR(regs); - SCI_CLR_INTR(regs); - - if (quickly) - return; - - /* - * reset the scsi bus, the interrupt routine does the rest - * or you can call sci_bus_reset(). - */ - regs->sci_icmd = SCI_ICMD_RST; - -} - -/* - * Operational functions - */ - -/* - * Start a SCSI command on a target - */ -sci_go(tgt, cmd_count, in_count, cmd_only) - target_info_t *tgt; - boolean_t cmd_only; -{ - sci_softc_t sci; - register spl_t s; - boolean_t disconn; - script_t scp; - boolean_t (*handler)(); - - LOG(1,"go"); - - sci = (sci_softc_t)tgt->hw_state; - - /* - * We cannot do real DMA. - */ -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - if (tgt->ior) - fdma_map(&tgt->fdma, tgt->ior); -#endif /*MACH_KERNEL*/ - - if ((tgt->cur_cmd == SCSI_CMD_WRITE) || - (tgt->cur_cmd == SCSI_CMD_LONG_WRITE)){ - io_req_t ior = tgt->ior; - register int len = ior->io_count; - - tgt->transient_state.out_count = len; - - if (len > PER_TGT_BUFF_SIZE) - len = PER_TGT_BUFF_SIZE; - bcopy( ior->io_data, - tgt->cmd_ptr + cmd_count, - len); - tgt->transient_state.copy_count = len; - - /* avoid leaks */ - if (len < tgt->block_size) { - bzero( tgt->cmd_ptr + cmd_count + len, - tgt->block_size - len); - tgt->transient_state.out_count = tgt->block_size; - } - } else { - tgt->transient_state.out_count = 0; - tgt->transient_state.copy_count = 0; - } - - tgt->transient_state.cmd_count = cmd_count; - - disconn = BGET(scsi_might_disconnect,tgt->masterno,tgt->target_id); - disconn = disconn && (sci->ntargets > 1); - disconn |= BGET(scsi_should_disconnect,tgt->masterno,tgt->target_id); - - /* - * Setup target state - */ - tgt->done = SCSI_RET_IN_PROGRESS; - - handler = (disconn) ? sci_err_disconn : sci_err_generic; - - switch (tgt->cur_cmd) { - case SCSI_CMD_READ: - case SCSI_CMD_LONG_READ: - LOG(0x13,"readop"); - scp = sci_script_data_in; - break; - case SCSI_CMD_WRITE: - case SCSI_CMD_LONG_WRITE: - LOG(0x14,"writeop"); - scp = sci_script_data_out; - break; - case SCSI_CMD_INQUIRY: - /* This is likely the first thing out: - do the synch neg if so */ - if (!cmd_only && ((tgt->flags&TGT_DID_SYNCH)==0)) { - scp = sci_script_try_synch; - tgt->flags |= TGT_TRY_SYNCH; - break; - } - case SCSI_CMD_REQUEST_SENSE: - case SCSI_CMD_MODE_SENSE: - case SCSI_CMD_RECEIVE_DIAG_RESULTS: - case SCSI_CMD_READ_CAPACITY: - case SCSI_CMD_READ_BLOCK_LIMITS: - case SCSI_CMD_READ_TOC: - case SCSI_CMD_READ_SUBCH: - case SCSI_CMD_READ_HEADER: - case 0xc4: /* despised: SCSI_CMD_DEC_PLAYBACK_STATUS */ - case 0xdd: /* despised: SCSI_CMD_NEC_READ_SUBCH_Q */ - case 0xde: /* despised: SCSI_CMD_NEC_READ_TOC */ - scp = sci_script_data_in; - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - case SCSI_CMD_MODE_SELECT: - case SCSI_CMD_REASSIGN_BLOCKS: - case SCSI_CMD_FORMAT_UNIT: - case 0xc9: /* vendor-spec: SCSI_CMD_DEC_PLAYBACK_CONTROL */ - tgt->transient_state.cmd_count = sizeof_scsi_command(tgt->cur_cmd); - tgt->transient_state.out_count = - cmd_count - tgt->transient_state.cmd_count; - scp = sci_script_data_out; - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - case SCSI_CMD_TEST_UNIT_READY: - /* - * Do the synch negotiation here, unless prohibited - * or done already - */ - if (tgt->flags & TGT_DID_SYNCH) { - scp = sci_script_cmd; - } else { - scp = sci_script_try_synch; - tgt->flags |= TGT_TRY_SYNCH; - cmd_only = FALSE; - } - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - default: - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - scp = sci_script_cmd; - } - - tgt->transient_state.script = scp; - tgt->transient_state.handler = handler; - tgt->transient_state.identify = (cmd_only) ? 0xff : - (disconn ? SCSI_IDENTIFY|SCSI_IFY_ENABLE_DISCONNECT : - SCSI_IDENTIFY); - - if (in_count) - tgt->transient_state.in_count = - (in_count < tgt->block_size) ? tgt->block_size : in_count; - else - tgt->transient_state.in_count = 0; - tgt->transient_state.dma_offset = 0; - - /* - * See if another target is currently selected on - * this SCSI bus, e.g. lock the sci structure. - * Note that it is the strategy routine's job - * to serialize ops on the same target as appropriate. - * XXX here and everywhere, locks! - */ - /* - * Protection viz reconnections makes it tricky. - */ -/* s = splbio();*/ - s = splhigh(); - - if (sci->wd.nactive++ == 0) - sci->wd.watchdog_state = SCSI_WD_ACTIVE; - - if (sci->state & SCI_STATE_BUSY) { - /* - * Queue up this target, note that this takes care - * of proper FIFO scheduling of the scsi-bus. - */ - LOG(3,"enqueue"); - enqueue_tail(&sci->waiting_targets, (queue_entry_t) tgt); - } else { - /* - * It is down to at most two contenders now, - * we will treat reconnections same as selections - * and let the scsi-bus arbitration process decide. - */ - sci->state |= SCI_STATE_BUSY; - sci->next_target = tgt; - sci_attempt_selection(sci); - /* - * Note that we might still lose arbitration.. - */ - } - splx(s); -} - -sci_attempt_selection(sci) - sci_softc_t sci; -{ - target_info_t *tgt; - register int out_count; - sci_padded_regmap_t *regs; - sci_dmaregs_t dmar; - register int cmd; - boolean_t ok; - scsi_ret_t ret; - - regs = sci->regs; - dmar = sci->dmar; - tgt = sci->next_target; - - LOG(4,"select"); - LOG(0x80+tgt->target_id,0); - - /* - * Init bus state variables and set registers. - */ - sci->active_target = tgt; - - /* reselection pending ? */ - if ((regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && - (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && - (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL))) - return; - - sci->script = tgt->transient_state.script; - sci->error_handler = tgt->transient_state.handler; - sci->done = SCSI_RET_IN_PROGRESS; - - sci->in_count = 0; - sci->out_count = 0; - sci->extra_byte = 0; - - /* - * This is a bit involved, but the bottom line is we want to - * know after we selected with or w/o ATN if the selection - * went well (ret) and if it is (ok) to send the command. - */ - ok = TRUE; - if (tgt->flags & TGT_DID_SYNCH) { - if (tgt->transient_state.identify == 0xff) { - /* Select w/o ATN */ - ret = sci_select_target(regs, sci->sc->initiator_id, - tgt->target_id, FALSE); - } else { - /* Select with ATN */ - ret = sci_select_target(regs, sci->sc->initiator_id, - tgt->target_id, TRUE); - if (ret == SCSI_RET_SUCCESS) { - register unsigned char icmd; - - while (SCI_CUR_PHASE(regs->sci_bus_csr) != SCSI_PHASE_MSG_OUT) - ; - icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); - icmd &= ~SCI_ICMD_ATN; - regs->sci_icmd = icmd; - SCI_ACK(regs,SCSI_PHASE_MSG_OUT); - ok = (sci_data_out(regs, SCSI_PHASE_MSG_OUT, - 1, &tgt->transient_state.identify) == 0); - } - } - } else if (tgt->flags & TGT_TRY_SYNCH) { - /* Select with ATN, do the synch xfer neg */ - ret = sci_select_target(regs, sci->sc->initiator_id, - tgt->target_id, TRUE); - if (ret == SCSI_RET_SUCCESS) { - while (SCI_CUR_PHASE(regs->sci_bus_csr) != SCSI_PHASE_MSG_OUT) - ; - ok = sci_dosynch( sci, regs->sci_csr, regs->sci_bus_csr); - } - } else { - ret = sci_select_target(regs, sci->sc->initiator_id, - tgt->target_id, FALSE); - } - - if (ret == SCSI_RET_DEVICE_DOWN) { - sci->done = ret; - sci_end(sci, regs->sci_csr, regs->sci_bus_csr); - return; - } - if ((ret != SCSI_RET_SUCCESS) || !ok) - return; - -/* time this out or do it via dma !! */ - while (SCI_CUR_PHASE(regs->sci_bus_csr) != SCSI_PHASE_CMD) - ; - - /* set dma pointer and counter to xfer command */ - out_count = tgt->transient_state.cmd_count; -#if 0 - SCI_ACK(regs,SCSI_PHASE_CMD); - sci_data_out(regs,SCSI_PHASE_CMD,out_count,tgt->cmd_ptr); - regs->sci_mode = SCI_MODE_PAR_CHK|SCI_MODE_DMA|SCI_MODE_MONBSY; -#else - SCI_DMADR_PUT(dmar,tgt->dma_ptr); - delay_1p2_us(); - SCI_TC_PUT(dmar,out_count); - dmar->sci_dma_dir = SCI_DMA_DIR_WRITE; - SCI_ACK(regs,SCSI_PHASE_CMD); - SCI_CLR_INTR(regs); - regs->sci_mode = SCI_MODE_PAR_CHK|SCI_MODE_DMA|SCI_MODE_MONBSY; - regs->sci_icmd = SCI_ICMD_DATA; - regs->sci_dma_send = 1; -#endif -} - -/* - * Interrupt routine - * Take interrupts from the chip - * - * Implementation: - * Move along the current command's script if - * all is well, invoke error handler if not. - */ -sci_intr(unit) -{ - register sci_softc_t sci; - register script_t scp; - register unsigned csr, bs, cmd; - register sci_padded_regmap_t *regs; - boolean_t try_match; -#if notyet - extern boolean_t rz_use_mapped_interface; - - if (rz_use_mapped_interface) - return SCI_intr(unit); -#endif - - LOG(5,"\n\tintr"); - - sci = sci_softc[unit]; - regs = sci->regs; - - /* ack interrupt */ - csr = regs->sci_csr; - bs = regs->sci_bus_csr; - cmd = regs->sci_icmd; -TR(regs->sci_mode); - SCI_CLR_INTR(regs); - -TR(csr); -TR(bs); -TR(cmd); -TRCHECK; - - if (cmd & SCI_ICMD_RST){ - sci_bus_reset(sci); - return; - } - - /* we got an interrupt allright */ - if (sci->active_target) - sci->wd.watchdog_state = SCSI_WD_ACTIVE; - - /* drop spurious calls */ - if ((csr & SCI_CSR_INT) == 0) { - LOG(2,"SPURIOUS"); - return; - } - - /* Note: reselect has I/O asserted, select has not */ - if ((sci->state & SCI_STATE_TARGET) || - ((bs & (SCI_BUS_BSY|SCI_BUS_SEL|SCI_BUS_IO)) == SCI_BUS_SEL)) { - sci_target_intr(sci,csr,bs); - return; - } - - scp = sci->script; - - /* Race: disconnecting, we get the disconnected notification - (csr sez BSY dropped) at the same time a reselect is active */ - if ((csr & SCI_CSR_DISC) && - scp && (scp->condition == SCI_PHASE_DISC)) { - (void) (*scp->action)(sci, csr, bs); - /* takes care of calling reconnect if necessary */ - return; - } - - /* check who got the bus */ - if ((scp == 0) || (cmd & SCI_ICMD_LST) || - ((bs & (SCI_BUS_BSY|SCI_BUS_SEL|SCI_BUS_IO)) == (SCI_BUS_SEL|SCI_BUS_IO))) { - sci_reconnect(sci, csr, bs); - return; - } - - if (SCRIPT_MATCH(csr,bs) != scp->condition) { - if (try_match = (*sci->error_handler)(sci, csr, bs)) { - csr = regs->sci_csr; - bs = regs->sci_bus_csr; - } - } else - try_match = TRUE; - - /* might have been side effected */ - scp = sci->script; - - if (try_match && (SCRIPT_MATCH(csr,bs) == scp->condition)) { - /* - * Perform the appropriate operation, - * then proceed - */ - if ((*scp->action)(sci, csr, bs)) { - /* might have been side effected */ - scp = sci->script; - sci->script = scp + 1; - } - } -} - - -sci_target_intr(sci) - register sci_softc_t sci; -{ - panic("SCI: TARGET MODE !!!\n"); -} - -/* - * All the many little things that the interrupt - * routine might switch to - */ -boolean_t -sci_end_transaction( sci, csr, bs) - register sci_softc_t sci; -{ - register sci_padded_regmap_t *regs = sci->regs; - char cmc; - - LOG(0x1f,"end_t"); - - /* Stop dma, no interrupt on disconnect */ - regs->sci_icmd = 0; - regs->sci_mode &= ~(SCI_MODE_DMA|SCI_MODE_MONBSY|SCI_MODE_DMA_IE); -/* dmar->sci_dma_dir = SCI_DMA_DIR_WRITE;/* make sure we steal not */ - - SCI_ACK(regs,SCSI_PHASE_MSG_IN); - - regs->sci_sel_enb = (1 << sci->sc->initiator_id); - - sci_data_in(regs, SCSI_PHASE_MSG_IN, 1, &cmc); - - if (cmc != SCSI_COMMAND_COMPLETE) - printf("{T%x}", cmc); - - /* check disconnected, clear all intr bits */ - while (regs->sci_bus_csr & SCI_BUS_BSY) - ; - SCI_CLR_INTR(regs); - SCI_ACK(regs,SCI_PHASE_DISC); - - if (!sci_end(sci, csr, bs)) { - SCI_CLR_INTR(regs); - (void) sci_reconnect(sci, csr, bs); - } - return FALSE; -} - -boolean_t -sci_end( sci, csr, bs) - register sci_softc_t sci; -{ - register target_info_t *tgt; - register io_req_t ior; - register sci_padded_regmap_t *regs = sci->regs; - boolean_t reconn_pending; - - LOG(6,"end"); - - tgt = sci->active_target; - - if ((tgt->done = sci->done) == SCSI_RET_IN_PROGRESS) - tgt->done = SCSI_RET_SUCCESS; - - sci->script = 0; - - if (sci->wd.nactive-- == 1) - sci->wd.watchdog_state = SCSI_WD_INACTIVE; - - /* check reconnection not pending */ - bs = regs->sci_bus_csr; - reconn_pending = ((bs & (SCI_BUS_BSY|SCI_BUS_SEL|SCI_BUS_IO)) == (SCI_BUS_SEL|SCI_BUS_IO)); - if (!reconn_pending) { - sci_release_bus(sci); - } else { - sci->active_target = 0; -/* sci->state &= ~SCI_STATE_BUSY; later */ - } - - if (ior = tgt->ior) { -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - fdma_unmap(&tgt->fdma, ior); -#endif /*MACH_KERNEL*/ - LOG(0xA,"ops->restart"); - (*tgt->dev_ops->restart)( tgt, TRUE); - if (reconn_pending) - sci->state &= ~SCI_STATE_BUSY; - } - - return (!reconn_pending); -} - -boolean_t -sci_release_bus(sci) - register sci_softc_t sci; -{ - boolean_t ret = FALSE; - - LOG(9,"release"); - - sci->script = 0; - - if (sci->state & SCI_STATE_COLLISION) { - - LOG(0xB,"collided"); - sci->state &= ~SCI_STATE_COLLISION; - sci_attempt_selection(sci); - - } else if (queue_empty(&sci->waiting_targets)) { - - sci->state &= ~SCI_STATE_BUSY; - sci->active_target = 0; - ret = TRUE; - - } else { - - LOG(0xC,"dequeue"); - sci->next_target = (target_info_t *) - dequeue_head(&sci->waiting_targets); - sci_attempt_selection(sci); - } - return ret; -} - -boolean_t -sci_get_status( sci, csr, bs) - register sci_softc_t sci; -{ - register sci_padded_regmap_t *regs = sci->regs; - register sci_dmaregs_t dmar = sci->dmar; - scsi2_status_byte_t status; - register target_info_t *tgt; - unsigned int len, mode; - - LOG(0xD,"get_status"); -TRWRAP; - - /* Stop dma */ - regs->sci_icmd = 0; - mode = regs->sci_mode; - regs->sci_mode = (mode & ~(SCI_MODE_DMA|SCI_MODE_DMA_IE)); - dmar->sci_dma_dir = SCI_DMA_DIR_WRITE;/* make sure we steal not */ - - sci->state &= ~SCI_STATE_DMA_IN; - - tgt = sci->active_target; - - if (len = sci->in_count) { - register int count; - SCI_TC_GET(dmar,count); - if ((tgt->cur_cmd != SCSI_CMD_READ) && - (tgt->cur_cmd != SCSI_CMD_LONG_READ)){ - len -= count; - } else { - if (count) { -#if 0 - this is incorrect and besides.. - tgt->ior->io_residual = count; -#endif - len -= count; - } - sci_copyin( tgt, tgt->transient_state.dma_offset, - len, 0, 0); - } - } - - /* to get the phase mismatch intr */ - regs->sci_mode = mode; - - SCI_ACK(regs,SCSI_PHASE_STATUS); - - sci_data_in(regs, SCSI_PHASE_STATUS, 1, &status.bits); - - SCI_TC_PUT(dmar,0); - - if (status.st.scsi_status_code != SCSI_ST_GOOD) { - scsi_error(sci->active_target, SCSI_ERR_STATUS, status.bits, 0); - sci->done = (status.st.scsi_status_code == SCSI_ST_BUSY) ? - SCSI_RET_RETRY : SCSI_RET_NEED_SENSE; - } else - sci->done = SCSI_RET_SUCCESS; - - return TRUE; -} - -boolean_t -sci_dma_in( sci, csr, bs) - register sci_softc_t sci; -{ - register target_info_t *tgt; - register sci_padded_regmap_t *regs = sci->regs; - register sci_dmaregs_t dmar = sci->dmar; - char *dma_ptr; - register int count; - boolean_t advance_script = TRUE; - - LOG(0xE,"dma_in"); - - /* - * Problem: the 5380 pipelines xfers between the scsibus and - * itself and between itself and the DMA engine --> halting ? - * In the dmaout direction all is ok, except that (see NCR notes) - * the EOP interrupt is generated before the pipe is empty. - * In the dmain direction (here) the interrupt comes when - * one too many bytes have been xferred on chip! - * - * More specifically, IF we asked for count blindly and we had - * more than count bytes coming (double buffering) we would endup - * actually xferring count+1 from the scsibus, but only count - * to memory [hopefully the last byte sits in the sci_datai reg]. - * This could be helped, except most times count is an exact multiple - * of the sector size which is where disks disconnect.... - * - * INSTEAD, we recognize here that we expect more than count bytes - * coming and set the DMA count to count-1 but keep sci->in_count - * above to count. This will be wrong if the target disconnects - * amidst, but we can cure it. - * - * The places where this has an effect are marked by "EXTRA_BYTE" - */ - - tgt = sci->active_target; - sci->state |= SCI_STATE_DMA_IN; - - /* ought to stop dma to start another */ - regs->sci_mode &= ~ (SCI_MODE_DMA|SCI_MODE_DMA_IE); - regs->sci_icmd = 0; - - if (sci->in_count == 0) { - /* - * Got nothing yet: either just sent the command - * or just reconnected - */ - register int avail; - - count = tgt->transient_state.in_count; - count = u_min(count, (PER_TGT_BURST_SIZE)); - avail = PER_TGT_BUFF_SIZE - tgt->transient_state.dma_offset; - count = u_min(count, avail); - - /* common case of 8k-or-less read ? */ - advance_script = (tgt->transient_state.in_count == count); - - } else { - - /* - * We received some data. - */ - register int offset, xferred, eb; - unsigned char extrab = regs->sci_idata; /* EXTRA_BYTE */ - - SCI_TC_GET(dmar,xferred); - assert(xferred == 0); -if (scsi_debug) { -printf("{B %x %x %x (%x)}", - sci->in_count, xferred, sci->extra_byte, extrab); -} - /* ++EXTRA_BYTE */ - xferred = sci->in_count - xferred; - eb = sci->extra_byte; - /* --EXTRA_BYTE */ - assert(xferred > 0); - tgt->transient_state.in_count -= xferred; - assert(tgt->transient_state.in_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - count = u_min(tgt->transient_state.in_count, (PER_TGT_BURST_SIZE)); - if (tgt->transient_state.dma_offset == PER_TGT_BUFF_SIZE) { - tgt->transient_state.dma_offset = 0; - } else { - register int avail; - avail = PER_TGT_BUFF_SIZE - tgt->transient_state.dma_offset; - count = u_min(count, avail); - } - advance_script = (tgt->transient_state.in_count == count); - - /* get some more */ - dma_ptr = tgt->dma_ptr + tgt->transient_state.dma_offset; - sci->in_count = count; - /* ++EXTRA_BYTE */ - if (!advance_script) { - sci->extra_byte = 1; /* that's the cure.. */ - count--; - } else - sci->extra_byte = 0; - /* --EXTRA_BYTE */ - SCI_TC_PUT(dmar,count); -/* regs->sci_icmd = 0;*/ - SCI_DMADR_PUT(dmar,dma_ptr); - delay_1p2_us(); - SCI_ACK(regs,SCSI_PHASE_DATAI); - SCI_CLR_INTR(regs); - regs->sci_mode |= (advance_script ? SCI_MODE_DMA - : (SCI_MODE_DMA|SCI_MODE_DMA_IE)); - dmar->sci_dma_dir = SCI_DMA_DIR_READ; - regs->sci_irecv = 1; - - /* copy what we got */ - sci_copyin( tgt, offset, xferred, eb, extrab); - - /* last chunk ? */ - return advance_script; - } - - sci->in_count = count; - dma_ptr = tgt->dma_ptr + tgt->transient_state.dma_offset; - - /* ++EXTRA_BYTE */ - if (!advance_script) { - sci->extra_byte = 1; /* that's the cure.. */ - count--; - } else - sci->extra_byte = 0; - /* --EXTRA_BYTE */ - - SCI_TC_PUT(dmar,count); -/* regs->sci_icmd = 0;*/ - SCI_DMADR_PUT(dmar,dma_ptr); - delay_1p2_us(); - SCI_ACK(regs,SCSI_PHASE_DATAI); - SCI_CLR_INTR(regs); - regs->sci_mode |= (advance_script ? SCI_MODE_DMA - : (SCI_MODE_DMA|SCI_MODE_DMA_IE)); - dmar->sci_dma_dir = SCI_DMA_DIR_READ; - regs->sci_irecv = 1; - - return advance_script; -} - -/* send data to target. Called in three different ways: - (a) to start transfer (b) to restart a bigger-than-8k - transfer (c) after reconnection - */ -int sci_delay = 1; - -boolean_t -sci_dma_out( sci, csr, bs) - register sci_softc_t sci; -{ - register sci_padded_regmap_t *regs = sci->regs; - register sci_dmaregs_t dmar = sci->dmar; - register char *dma_ptr; - register target_info_t *tgt; - boolean_t advance_script = TRUE; - int count = sci->out_count; - spl_t s; - register int tmp; - - LOG(0xF,"dma_out"); - - tgt = sci->active_target; - sci->state &= ~SCI_STATE_DMA_IN; - - if (sci->out_count == 0) { - /* - * Nothing committed: either just sent the - * command or reconnected - */ - register int remains; - - /* ought to stop dma to start another */ - regs->sci_mode &= ~ (SCI_MODE_DMA|SCI_MODE_DMA_IE); - dmar->sci_dma_dir = SCI_DMA_DIR_READ;/*hold it */ - - regs->sci_icmd = SCI_ICMD_DATA; - - SCI_ACK(regs,SCSI_PHASE_DATAO); - - count = tgt->transient_state.out_count; - count = u_min(count, (PER_TGT_BURST_SIZE)); - remains = PER_TGT_BUFF_SIZE - tgt->transient_state.dma_offset; - count = u_min(count, remains); - - /* common case of 8k-or-less write ? */ - advance_script = (tgt->transient_state.out_count == count); - } else { - /* - * We sent some data. - * Also, take care of bogus interrupts - */ - register int offset, xferred; - -if (sci_delay & 1) delay(1000); - /* ought to stop dma to start another */ - regs->sci_mode &= ~ (SCI_MODE_DMA|SCI_MODE_DMA_IE); - dmar->sci_dma_dir = SCI_DMA_DIR_READ;/*hold it */ -/* regs->sci_icmd = SCI_ICMD_DATA; */ - - SCI_TC_GET(dmar,xferred); -if (xferred) printf("{A %x}", xferred); - xferred = sci->out_count - xferred; - assert(xferred > 0); - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - count = u_min(tgt->transient_state.out_count, (PER_TGT_BURST_SIZE)); - if (tgt->transient_state.dma_offset == PER_TGT_BUFF_SIZE) { - tgt->transient_state.dma_offset = 0; - } else { - register int remains; - remains = PER_TGT_BUFF_SIZE - tgt->transient_state.dma_offset; - count = u_min(count, remains); - } - /* last chunk ? */ - if (tgt->transient_state.out_count == count) - goto quickie; - - /* ship some more */ - dma_ptr = tgt->dma_ptr + - tgt->transient_state.cmd_count + tgt->transient_state.dma_offset; - sci->out_count = count; - /* - * Mistery: sometimes the first byte - * of an 8k chunk is missing from the tape, it must - * be that somehow touching the 5380 registers - * after the dma engine is ready screws up: false DRQ? - */ -s = splhigh(); - SCI_TC_PUT(dmar,count); -/* SCI_CLR_INTR(regs);*/ - regs->sci_mode = SCI_MODE_PAR_CHK | SCI_MODE_DMA | - SCI_MODE_MONBSY | SCI_MODE_DMA_IE; -/* regs->sci_icmd = SCI_ICMD_DATA;*/ - dmar->sci_dma_dir = SCI_DMA_DIR_WRITE; - SCI_DMADR_PUT(dmar,dma_ptr); - delay_1p2_us(); - - regs->sci_dma_send = 1; -splx(s); - /* copy some more data */ - sci_copyout(tgt, offset, xferred); - return FALSE; - } - -quickie: - sci->out_count = count; - dma_ptr = tgt->dma_ptr + - tgt->transient_state.cmd_count + tgt->transient_state.dma_offset; - tmp = (advance_script ? - SCI_MODE_PAR_CHK|SCI_MODE_DMA|SCI_MODE_MONBSY: - SCI_MODE_PAR_CHK|SCI_MODE_DMA|SCI_MODE_MONBSY|SCI_MODE_DMA_IE); -s = splhigh(); - SCI_TC_PUT(dmar,count); -/* SCI_CLR_INTR(regs);*/ - regs->sci_mode = tmp; -/* regs->sci_icmd = SCI_ICMD_DATA;*/ - SCI_DMADR_PUT(dmar,dma_ptr); - delay_1p2_us(); - dmar->sci_dma_dir = SCI_DMA_DIR_WRITE; - regs->sci_dma_send = 1; -splx(s); - - return advance_script; -} - -/* disconnect-reconnect ops */ - -/* get the message in via dma */ -boolean_t -sci_msg_in(sci, csr, bs) - register sci_softc_t sci; -{ - register target_info_t *tgt; - char *dma_ptr; - register sci_padded_regmap_t *regs = sci->regs; - register sci_dmaregs_t dmar = sci->dmar; - - LOG(0x15,"msg_in"); - - tgt = sci->active_target; - - dma_ptr = tgt->dma_ptr; - /* We would clobber the data for READs */ - if (sci->state & SCI_STATE_DMA_IN) { - register int offset; - offset = tgt->transient_state.cmd_count + tgt->transient_state.dma_offset; - dma_ptr += offset; - } - - /* ought to stop dma to start another */ - regs->sci_mode &= ~ (SCI_MODE_DMA|SCI_MODE_DMA_IE); - regs->sci_icmd = 0; - - /* We only really expect two bytes */ - SCI_TC_PUT(dmar,sizeof(scsi_command_group_0)); -/* regs->sci_icmd = 0*/ - SCI_DMADR_PUT(dmar,dma_ptr); - delay_1p2_us(); - SCI_ACK(regs,SCSI_PHASE_MSG_IN); - SCI_CLR_INTR(regs); - regs->sci_mode |= SCI_MODE_DMA; - dmar->sci_dma_dir = SCI_DMA_DIR_READ; - regs->sci_irecv = 1; - - return TRUE; -} - -/* check the message is indeed a DISCONNECT */ -boolean_t -sci_disconnect(sci, csr, bs) - register sci_softc_t sci; -{ - register int len; - boolean_t ok = FALSE; - register sci_dmaregs_t dmar = sci->dmar; - register char *msgs; - unsigned int offset; - - - SCI_TC_GET(dmar,len); - len = sizeof(scsi_command_group_0) - len; - PRINT(("{G%d}",len)); - - /* wherever it was, take it from there */ - SCI_DMADR_GET(dmar,offset); - msgs = (char*)sci->buff + offset - len; - - if ((len == 0) || (len > 2)) - ok = FALSE; - else { - /* A SDP message preceeds it in non-completed READs */ - ok = ((msgs[0] == SCSI_DISCONNECT) || /* completed op */ - ((msgs[0] == SCSI_SAVE_DATA_POINTER) && /* incomplete */ - (msgs[1] == SCSI_DISCONNECT))); - } - if (!ok) - printf("[tgt %d bad msg (%d): %x]", - sci->active_target->target_id, len, *msgs); - - return TRUE; -} - -/* save all relevant data, free the BUS */ -boolean_t -sci_disconnected(sci, csr, bs) - register sci_softc_t sci; -{ - register target_info_t *tgt; - sci_padded_regmap_t *regs = sci->regs; - - regs->sci_mode &= ~(SCI_MODE_MONBSY|SCI_MODE_DMA); - SCI_CLR_INTR(regs);/*retriggered by MONBSY cuz intr routine did CLR */ - SCI_ACK(regs,SCI_PHASE_DISC); - - LOG(0x16,"disconnected"); - - sci_disconnect(sci,csr,bs); - - tgt = sci->active_target; - tgt->flags |= TGT_DISCONNECTED; - tgt->transient_state.handler = sci->error_handler; - /* the rest has been saved in sci_err_disconn() */ - - PRINT(("{D%d}", tgt->target_id)); - - sci_release_bus(sci); - - return FALSE; -} - -/* get reconnect message, restore BUS */ -boolean_t -sci_reconnect(sci, csr, bs) - register sci_softc_t sci; -{ - register target_info_t *tgt; - sci_padded_regmap_t *regs; - register int id; - int msg; - - LOG(0x17,"reconnect"); - - if (sci->wd.nactive == 0) { - LOG(2,"SPURIOUS"); - return FALSE; - } - - regs = sci->regs; - - regs->sci_mode &= ~SCI_MODE_PAR_CHK; - id = regs->sci_data;/*parity!*/ - regs->sci_mode |= SCI_MODE_PAR_CHK; - - /* xxx check our id is in there */ - - id &= ~(1 << sci->sc->initiator_id); - { - register int i; - for (i = 0; i < 8; i++) - if (id & (1 << i)) break; -if (i == 8) {printf("{P%x}", id);return;} - id = i; - } - regs->sci_icmd = SCI_ICMD_BSY; - while (regs->sci_bus_csr & SCI_BUS_SEL) - ; - regs->sci_icmd = 0; - delay_1p2_us(); - while ( ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) && - ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) && - ((regs->sci_bus_csr & SCI_BUS_BSY) == 0)) - ; - - regs->sci_mode |= SCI_MODE_MONBSY; - - /* Now should wait for correct phase: REQ signals it */ - while ( ((regs->sci_bus_csr & SCI_BUS_REQ) == 0) && - ((regs->sci_bus_csr & SCI_BUS_REQ) == 0) && - ((regs->sci_bus_csr & SCI_BUS_REQ) == 0)) - ; - - /* - * See if this reconnection collided with a selection attempt - */ - if (sci->state & SCI_STATE_BUSY) - sci->state |= SCI_STATE_COLLISION; - - sci->state |= SCI_STATE_BUSY; - - /* Get identify msg */ - bs = regs->sci_bus_csr; -if (SCI_CUR_PHASE(bs) != SCSI_PHASE_MSG_IN) gimmeabreak(); - SCI_ACK(regs,SCSI_PHASE_MSG_IN); - msg = 0; - sci_data_in(regs, SCSI_PHASE_MSG_IN, 1, &msg); - regs->sci_mode = SCI_MODE_PAR_CHK|SCI_MODE_DMA|SCI_MODE_MONBSY; - regs->sci_sel_enb = 0; - - if (msg != SCSI_IDENTIFY) - printf("{I%x %x}", id, msg); - - tgt = sci->sc->target[id]; - if (id > 7 || tgt == 0) panic("sci_reconnect"); - - PRINT(("{R%d}", id)); - if (sci->state & SCI_STATE_COLLISION) - PRINT(("[B %d-%d]", sci->active_target->target_id, id)); - - LOG(0x80+id,0); - - sci->active_target = tgt; - tgt->flags &= ~TGT_DISCONNECTED; - - sci->script = tgt->transient_state.script; - sci->error_handler = tgt->transient_state.handler; - sci->in_count = 0; - sci->out_count = 0; - - /* Should get a phase mismatch when tgt changes phase */ - - return TRUE; -} - - - -/* do the synch negotiation */ -boolean_t -sci_dosynch( sci, csr, bs) - register sci_softc_t sci; -{ - /* - * Phase is MSG_OUT here, cmd has not been xferred - */ - int len; - register target_info_t *tgt; - register sci_padded_regmap_t *regs = sci->regs; - unsigned char off, icmd; - register unsigned char *p; - - regs->sci_mode |= SCI_MODE_MONBSY; - - LOG(0x11,"dosync"); - - /* ATN still asserted */ - SCI_ACK(regs,SCSI_PHASE_MSG_OUT); - - tgt = sci->active_target; - - tgt->flags |= TGT_DID_SYNCH; /* only one chance */ - tgt->flags &= ~TGT_TRY_SYNCH; - - p = (unsigned char *)tgt->cmd_ptr + tgt->transient_state.cmd_count + - tgt->transient_state.dma_offset; - p[0] = SCSI_IDENTIFY; - p[1] = SCSI_EXTENDED_MESSAGE; - p[2] = 3; - p[3] = SCSI_SYNC_XFER_REQUEST; - /* We cannot run synchronous */ -#define sci_to_scsi_period(x) 0xff -#define scsi_period_to_sci(x) (x) - off = 0; - p[4] = sci_to_scsi_period(sci_min_period); - p[5] = off; - - /* xfer all but last byte with ATN set */ - sci_data_out(regs, SCSI_PHASE_MSG_OUT, - sizeof(scsi_synch_xfer_req_t), p); - icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); - icmd &= ~SCI_ICMD_ATN; - regs->sci_icmd = icmd; - sci_data_out(regs, SCSI_PHASE_MSG_OUT, 1, - &p[sizeof(scsi_synch_xfer_req_t)]); - - /* wait for phase change */ - while (regs->sci_csr & SCI_CSR_PHASE_MATCH) - ; - bs = regs->sci_bus_csr; - - /* The standard sez there nothing else the target can do but.. */ - if (SCI_CUR_PHASE(bs) != SCSI_PHASE_MSG_IN) - panic("sci_dosync");/* XXX put offline */ - -msgin: - /* ack */ - SCI_ACK(regs,SCSI_PHASE_MSG_IN); - - /* get answer */ - len = sizeof(scsi_synch_xfer_req_t); - len = sci_data_in(regs, SCSI_PHASE_MSG_IN, len, p); - - /* do not cancel the phase mismatch interrupt ! */ - - /* look at the answer and see if we like it */ - if (len || (p[0] != SCSI_EXTENDED_MESSAGE)) { - /* did not like it at all */ - printf(" did not like SYNCH xfer "); - } else { - /* will NOT do synch */ - printf(" but we cannot do SYNCH xfer "); - tgt->sync_period = scsi_period_to_sci(p[3]); - tgt->sync_offset = p[4]; - /* sanity */ - if (tgt->sync_offset != 0) - printf(" ?OFFSET %x? ", tgt->sync_offset); - } - - /* wait for phase change */ - while (regs->sci_csr & SCI_CSR_PHASE_MATCH) - ; - bs = regs->sci_bus_csr; - - /* phase should be command now */ - /* continue with simple command script */ - sci->error_handler = sci_err_generic; - sci->script = sci_script_cmd; - - if (SCI_CUR_PHASE(bs) == SCSI_PHASE_CMD ) - return TRUE; - -/* sci->script++;*/ - if (SCI_CUR_PHASE(bs) == SCSI_PHASE_STATUS ) - return TRUE; /* intr is pending */ - - sci->script++; - if (SCI_CUR_PHASE(bs) == SCSI_PHASE_MSG_IN ) - return TRUE; - - if ((bs & SCI_BUS_BSY) == 0) /* uhu? disconnected */ - return sci_end_transaction(sci, regs->sci_csr, regs->sci_bus_csr); - - panic("sci_dosynch"); - return FALSE; -} - -/* - * The bus was reset - */ -sci_bus_reset(sci) - register sci_softc_t sci; -{ - register target_info_t *tgt; - register sci_padded_regmap_t *regs = sci->regs; - int i; - - LOG(0x21,"bus_reset"); - - /* - * Clear bus descriptor - */ - sci->script = 0; - sci->error_handler = 0; - sci->active_target = 0; - sci->next_target = 0; - sci->state = 0; - queue_init(&sci->waiting_targets); - sci->wd.nactive = 0; - sci_reset(sci, TRUE); - - printf("sci%d: (%d) bus reset ", sci->sc->masterno, ++sci->wd.reset_count); - delay(scsi_delay_after_reset); /* some targets take long to reset */ - - if (sci->sc == 0) /* sanity */ - return; - - scsi_bus_was_reset(sci->sc); -} - -/* - * Error handlers - */ - -/* - * Generic, default handler - */ -boolean_t -sci_err_generic(sci, csr, bs) - register sci_softc_t sci; -{ - register int cond = sci->script->condition; - - LOG(0x10,"err_generic"); - - if (SCI_CUR_PHASE(bs) == SCSI_PHASE_STATUS) - return sci_err_to_status(sci, csr, bs); - gimmeabreak(); - return FALSE; -} - -/* - * Handle generic errors that are reported as - * an unexpected change to STATUS phase - */ -sci_err_to_status(sci, csr, bs) - register sci_softc_t sci; -{ - script_t scp = sci->script; - - LOG(0x20,"err_tostatus"); - while (SCSI_PHASE(scp->condition) != SCSI_PHASE_STATUS) - scp++; - sci->script = scp; -#if 0 - /* - * Normally, we would already be able to say the command - * is in error, e.g. the tape had a filemark or something. - * But in case we do disconnected mode WRITEs, it is quite - * common that the following happens: - * dma_out -> disconnect -> reconnect - * and our script might expect at this point that the dma - * had to be restarted (it didn't know it was completed - * because the tape record is shorter than we asked for). - * And in any event.. it is both correct and cleaner to - * declare error iff the STATUS byte says so. - */ - sci->done = SCSI_RET_NEED_SENSE; -#endif - return TRUE; -} - -/* - * Watch for a disconnection - */ -boolean_t -sci_err_disconn(sci, csr, bs) - register sci_softc_t sci; -{ - register sci_padded_regmap_t *regs; - register sci_dmaregs_t dmar = sci->dmar; - register target_info_t *tgt; - int count; - - LOG(0x18,"err_disconn"); - - if (SCI_CUR_PHASE(bs) != SCSI_PHASE_MSG_IN) - return sci_err_generic(sci, csr, bs); - - regs = sci->regs; - - tgt = sci->active_target; - - switch (SCSI_PHASE(sci->script->condition)) { - case SCSI_PHASE_DATAO: - LOG(0x1b,"+DATAO"); - -if (sci_delay & 1) delay(1000); - /* Stop dma */ - regs->sci_icmd = 0; - regs->sci_mode &= ~(SCI_MODE_DMA|SCI_MODE_DMA_IE); - dmar->sci_dma_dir = SCI_DMA_DIR_READ;/* make sure we steal not */ - - if (sci->out_count) { - register int xferred, offset; - - SCI_TC_GET(dmar,xferred); -if (scsi_debug) -printf("{O %x %x}", xferred, sci->out_count); - /* 5380 prefetches */ - xferred = sci->out_count - xferred - 1; -/* assert(xferred > 0);*/ - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - if (tgt->transient_state.dma_offset >= PER_TGT_BUFF_SIZE) - tgt->transient_state.dma_offset = 0; - - sci_copyout( tgt, offset, xferred); - - } - tgt->transient_state.script = sci_script_data_out; - break; - - case SCSI_PHASE_DATAI: - LOG(0x19,"+DATAI"); - - /* Stop dma */ - regs->sci_icmd = 0; - regs->sci_mode &= ~(SCI_MODE_DMA|SCI_MODE_DMA_IE); - dmar->sci_dma_dir = SCI_DMA_DIR_WRITE;/* make sure we steal not */ - - if (sci->in_count) { - register int offset, xferred; -/* unsigned char extrab = regs->sci_idata;*/ - - SCI_TC_GET(dmar,xferred); - /* ++EXTRA_BYTE */ -if (scsi_debug) -printf("{A %x %x %x}", xferred, sci->in_count, sci->extra_byte); - xferred = sci->in_count - xferred - sci->extra_byte; - /* ++EXTRA_BYTE */ - assert(xferred > 0); - tgt->transient_state.in_count -= xferred; - assert(tgt->transient_state.in_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - if (tgt->transient_state.dma_offset >= PER_TGT_BUFF_SIZE) - tgt->transient_state.dma_offset = 0; - - /* copy what we got */ - sci_copyin( tgt, offset, xferred, 0, 0/*extrab*/); - } - tgt->transient_state.script = sci_script_data_in; - break; - - case SCSI_PHASE_STATUS: - /* will have to restart dma */ - SCI_TC_GET(dmar,count); - if (sci->state & SCI_STATE_DMA_IN) { - register int offset, xferred; -/* unsigned char extrab = regs->sci_idata;*/ - - LOG(0x1a,"+STATUS+R"); - - - /* Stop dma */ - regs->sci_icmd = 0; - regs->sci_mode &= ~(SCI_MODE_DMA|SCI_MODE_DMA_IE); - dmar->sci_dma_dir = SCI_DMA_DIR_WRITE;/* make sure we steal not */ - - /* ++EXTRA_BYTE */ -if (scsi_debug) -printf("{A %x %x %x}", count, sci->in_count, sci->extra_byte); - xferred = sci->in_count - count - sci->extra_byte; - /* ++EXTRA_BYTE */ - assert(xferred > 0); - tgt->transient_state.in_count -= xferred; -/* assert(tgt->transient_state.in_count > 0);*/ - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - if (tgt->transient_state.dma_offset >= PER_TGT_BUFF_SIZE) - tgt->transient_state.dma_offset = 0; - - /* copy what we got */ - sci_copyin( tgt, offset, xferred, 0, 0/*/extrab*/); - - tgt->transient_state.script = sci_script_data_in; - if (tgt->transient_state.in_count == 0) - tgt->transient_state.script++; - - } else { - - LOG(0x1d,"+STATUS+W"); - -if (sci_delay & 1) delay(1000); - /* Stop dma */ - regs->sci_icmd = 0; - regs->sci_mode &= ~(SCI_MODE_DMA|SCI_MODE_DMA_IE); - dmar->sci_dma_dir = SCI_DMA_DIR_READ;/* make sure we steal not */ - -if (scsi_debug) -printf("{O %x %x}", count, sci->out_count); - if ((count == 0) && (tgt->transient_state.out_count == sci->out_count)) { - /* all done */ - tgt->transient_state.script = &sci_script_data_out[1]; - tgt->transient_state.out_count = 0; - } else { - register int xferred, offset; - - /* how much we xferred */ - xferred = sci->out_count - count - 1;/*prefetch*/ - - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - if (tgt->transient_state.dma_offset >= PER_TGT_BUFF_SIZE) - tgt->transient_state.dma_offset = 0; - - sci_copyout( tgt, offset, xferred); - - tgt->transient_state.script = sci_script_data_out; - } - sci->out_count = 0; - } - break; - default: - gimmeabreak(); - } - sci->extra_byte = 0; - -/* SCI_ACK(regs,SCSI_PHASE_MSG_IN); later */ - (void) sci_msg_in(sci,csr,bs); - - regs->sci_sel_enb = (1 << sci->sc->initiator_id); - - sci->script = sci_script_disconnect; - - return FALSE; -} - -/* - * Watchdog - * - */ -sci_reset_scsibus(sci) - register sci_softc_t sci; -{ - register target_info_t *tgt = sci->active_target; - if (tgt) { - int cnt; - SCI_TC_GET(sci->dmar,cnt); - log( LOG_KERN, - "Target %d was active, cmd x%x in x%x out x%x Sin x%x Sou x%x dmalen x%x\n", - tgt->target_id, tgt->cur_cmd, - tgt->transient_state.in_count, tgt->transient_state.out_count, - sci->in_count, sci->out_count, cnt); - } - sci->regs->sci_icmd = SCI_ICMD_RST; - delay(25); -} - -/* - * Copy routines - */ -/*static*/ -sci_copyin(tgt, offset, len, isaobb, obb) - register target_info_t *tgt; - unsigned char obb; -{ - register char *from, *to; - register int count; - - count = tgt->transient_state.copy_count; - - from = tgt->cmd_ptr + offset; - to = tgt->ior->io_data + count; - tgt->transient_state.copy_count = count + len; - - bcopy( from, to, len); - /* check for last, poor little odd byte */ - if (isaobb) { - to += len; - to[-1] = obb; - } -} - -/*static*/ -sci_copyout( tgt, offset, len) - register target_info_t *tgt; -{ - register char *from, *to; - register int count, olen; - unsigned char c; - char *p; - - count = tgt->ior->io_count - tgt->transient_state.copy_count; - if (count > 0) { - - len = u_min(count, len); - offset += tgt->transient_state.cmd_count; - - count = tgt->transient_state.copy_count; - tgt->transient_state.copy_count = count + len; - - from = tgt->ior->io_data + count; - to = tgt->cmd_ptr + offset; - - bcopy(from, to, len); - - } -} - -#endif /*NSCI > 0*/ - diff --git a/scsi/adapters/scsi_53C700.h b/scsi/adapters/scsi_53C700.h deleted file mode 100644 index 224fc5b..0000000 --- a/scsi/adapters/scsi_53C700.h +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ -/* - * File: scsi_53C700.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 8/91 - * - * Defines for the NCR 53C700 (SCSI I/O Processor) - */ - -/* - * Register map - */ - -typedef struct { - volatile unsigned char siop_scntl0; /* rw: SCSI control reg 0 */ - volatile unsigned char siop_scntl1; /* rw: SCSI control reg 1 */ - volatile unsigned char siop_sdid; /* rw: SCSI Destination ID */ - volatile unsigned char siop_sien; /* rw: SCSI Interrupt Enable */ - volatile unsigned char siop_scid; /* rw: SCSI Chip ID reg */ - volatile unsigned char siop_sxfer; /* rw: SCSI Transfer reg */ - volatile unsigned char siop_sodl; /* rw: SCSI Output Data Latch */ - volatile unsigned char siop_socl; /* rw: SCSI Output Control Latch */ - volatile unsigned char siop_sfbr; /* ro: SCSI First Byte Received */ - volatile unsigned char siop_sidl; /* ro: SCSI Input Data Latch */ - volatile unsigned char siop_sbdl; /* ro: SCSI Bus Data Lines */ - volatile unsigned char siop_sbcl; /* ro: SCSI Bus Control Lines */ - volatile unsigned char siop_dstat; /* ro: DMA status */ - volatile unsigned char siop_sstat0; /* ro: SCSI status reg 0 */ - volatile unsigned char siop_sstat1; /* ro: SCSI status reg 1 */ - volatile unsigned char siop_sstat2; /* ro: SCSI status reg 2 */ - volatile unsigned char siop_res1; - volatile unsigned char siop_res2; - volatile unsigned char siop_res3; - volatile unsigned char siop_res4; - volatile unsigned char siop_ctest0; /* ro: Chip test register 0 */ - volatile unsigned char siop_ctest1; /* ro: Chip test register 1 */ - volatile unsigned char siop_ctest2; /* ro: Chip test register 2 */ - volatile unsigned char siop_ctest3; /* ro: Chip test register 3 */ - volatile unsigned char siop_ctest4; /* rw: Chip test register 4 */ - volatile unsigned char siop_ctest5; /* rw: Chip test register 5 */ - volatile unsigned char siop_ctest6; /* rw: Chip test register 6 */ - volatile unsigned char siop_ctest7; /* rw: Chip test register 7 */ - volatile unsigned char siop_temp0; /* rw: Temporary Stack reg */ - volatile unsigned char siop_temp1; - volatile unsigned char siop_temp2; - volatile unsigned char siop_temp3; - volatile unsigned char siop_dfifo; /* rw: DMA FIFO */ - volatile unsigned char siop_istat; /* rw: Interrupt Status reg */ - volatile unsigned char siop_res5; - volatile unsigned char siop_res6; - volatile unsigned char siop_dbc0; /* rw: DMA Byte Counter reg */ - volatile unsigned char siop_dbc1; - volatile unsigned char siop_dbc2; - volatile unsigned char siop_dcmd; /* rw: DMA Command Register */ - volatile unsigned char siop_dnad0; /* rw: DMA Next Address */ - volatile unsigned char siop_dnad1; - volatile unsigned char siop_dnad2; - volatile unsigned char siop_dnad3; - volatile unsigned char siop_dsp0; /* rw: DMA SCRIPTS Pointer reg */ - volatile unsigned char siop_dsp1; - volatile unsigned char siop_dsp2; - volatile unsigned char siop_dsp3; - volatile unsigned char siop_dsps0; /* rw: DMA SCRIPTS Pointer Save reg */ - volatile unsigned char siop_dsps1; - volatile unsigned char siop_dsps2; - volatile unsigned char siop_dsps3; - volatile unsigned char siop_dmode; /* rw: DMA Mode reg */ - volatile unsigned char siop_res7; - volatile unsigned char siop_res8; - volatile unsigned char siop_res9; - volatile unsigned char siop_res10; - volatile unsigned char siop_dien; /* rw: DMA Interrupt Enable */ - volatile unsigned char siop_dwt; /* rw: DMA Watchdog Timer */ - volatile unsigned char siop_dcntl; /* rw: DMA Control reg */ - volatile unsigned char siop_res11; - volatile unsigned char siop_res12; - volatile unsigned char siop_res13; - volatile unsigned char siop_res14; - -} siop_regmap_t; - -/* - * Register defines - */ - -/* Scsi control register 0 (scntl0) */ - -#define SIOP_SCNTL0_ARB 0xc0 /* Arbitration mode */ -# define SIOP_ARB_SIMPLE 0x00 -# define SIOP_ARB_FULL 0xc0 -#define SIOP_SCNTL0_START 0x20 /* Start Sequence */ -#define SIOP_SCNTL0_WATN 0x10 /* (Select) With ATN */ -#define SIOP_SCNTL0_EPC 0x08 /* Enable Parity Checking */ -#define SIOP_SCNTL0_EPG 0x04 /* Enable Parity Generation */ -#define SIOP_SCNTL0_AAP 0x02 /* Assert ATN on Parity Error */ -#define SIOP_SCNTL0_TRG 0x01 /* Target Mode */ - -/* Scsi control register 1 (scntl1) */ - -#define SIOP_SCNTL1_EXC 0x80 /* Extra Clock Cycle of data setup */ -#define SIOP_SCNTL1_ADB 0x40 /* Assert Data Bus */ -#define SIOP_SCNTL1_ESR 0x20 /* Enable Selection/Reselection */ -#define SIOP_SCNTL1_CON 0x10 /* Connected */ -#define SIOP_SCNTL1_RST 0x08 /* Assert RST */ -#define SIOP_SCNTL1_PAR 0x04 /* Force bad Parity */ -#define SIOP_SCNTL1_SND 0x02 /* Start Send operation */ -#define SIOP_SCNTL1_RCV 0x01 /* Start Receive operation */ - -/* Scsi interrupt enable register (sien) */ - -#define SIOP_SIEN_M_A 0x80 /* Phase Mismatch or ATN active */ -#define SIOP_SIEN_FC 0x40 /* Function Complete */ -#define SIOP_SIEN_STO 0x20 /* (Re)Selection timeout */ -#define SIOP_SIEN_SEL 0x10 /* (Re)Selected */ -#define SIOP_SIEN_SGE 0x08 /* SCSI Gross Error */ -#define SIOP_SIEN_UDC 0x04 /* Unexpected Disconnect */ -#define SIOP_SIEN_RST 0x02 /* RST asserted */ -#define SIOP_SIEN_PAR 0x01 /* Parity Error */ - -/* Scsi chip ID (scid) */ - -#define SIOP_SCID_VALUE(i) (1<<i) - -/* Scsi transfer register (sxfer) */ - -#define SIOP_SXFER_DHP 0x80 /* Disable Halt on Parity error/ ATN asserted */ -#define SIOP_SXFER_TP 0x70 /* Synch Transfer Period */ - /* see specs for formulas: - Period = TCP * (4 + XFERP ) - TCP = 1 + CLK + 1..2; - */ -#define SIOP_SXFER_MO 0x0f /* Synch Max Offset */ -# define SIOP_MAX_OFFSET 8 - -/* Scsi output data latch register (sodl) */ - -/* Scsi output control latch register (socl) */ - -#define SIOP_REQ 0x80 /* SCSI signal <x> asserted */ -#define SIOP_ACK 0x40 -#define SIOP_BSY 0x20 -#define SIOP_SEL 0x10 -#define SIOP_ATN 0x08 -#define SIOP_MSG 0x04 -#define SIOP_CD 0x02 -#define SIOP_IO 0x01 - -#define SIOP_PHASE(socl) SCSI_PHASE(socl) - -/* Scsi first byte received register (sfbr) */ - -/* Scsi input data latch register (sidl) */ - -/* Scsi bus data lines register (sbdl) */ - -/* Scsi bus control lines register (sbcl). Same as socl */ - -/* DMA status register (dstat) */ - -#define SIOP_DSTAT_DFE 0x80 /* DMA FIFO empty */ -#define SIOP_DSTAT_RES 0x60 -#define SIOP_DSTAT_ABRT 0x10 /* Aborted */ -#define SIOP_DSTAT_SSI 0x08 /* SCRIPT Single Step */ -#define SIOP_DSTAT_SIR 0x04 /* SCRIPT Interrupt Instruction */ -#define SIOP_DSTAT_WTD 0x02 /* Watchdog Timeout Detected */ -#define SIOP_DSTAT_OPC 0x01 /* Invalid SCRIPTS Opcode */ - -/* Scsi status register 0 (sstat0) */ - -#define SIOP_SSTAT0_M_A 0x80 /* Phase Mismatch or ATN active */ -#define SIOP_SSTAT0_FC 0x40 /* Function Complete */ -#define SIOP_SSTAT0_STO 0x20 /* (Re)Selection timeout */ -#define SIOP_SSTAT0_SEL 0x10 /* (Re)Selected */ -#define SIOP_SSTAT0_SGE 0x08 /* SCSI Gross Error */ -#define SIOP_SSTAT0_UDC 0x04 /* Unexpected Disconnect */ -#define SIOP_SSTAT0_RST 0x02 /* RST asserted */ -#define SIOP_SSTAT0_PAR 0x01 /* Parity Error */ - -/* Scsi status register 1 (sstat1) */ - -#define SIOP_SSTAT1_ILF 0x80 /* Input latch (sidl) full */ -#define SIOP_SSTAT1_ORF 0x40 /* output reg (sodr) full */ -#define SIOP_SSTAT1_OLF 0x20 /* output latch (sodl) full */ -#define SIOP_SSTAT1_AIP 0x10 /* Arbitration in progress */ -#define SIOP_SSTAT1_LOA 0x08 /* Lost arbitration */ -#define SIOP_SSTAT1_WOA 0x04 /* Won arbitration */ -#define SIOP_SSTAT1_RST 0x02 /* SCSI RST current value */ -#define SIOP_SSTAT1_SDP 0x01 /* SCSI SDP current value */ - -/* Scsi status register 2 (sstat2) */ - -#define SIOP_SSTAT2_FF 0xf0 /* SCSI FIFO flags (bytecount) */ -# define SIOP_SCSI_FIFO_DEEP 8 -#define SIOP_SSTAT2_SDP 0x08 /* Latched (on REQ) SCSI SDP */ -#define SIOP_SSTAT2_MSG 0x04 /* Latched SCSI phase */ -#define SIOP_SSTAT2_CD 0x02 -#define SIOP_SSTAT2_IO 0x01 - -/* Chip test register 0 (ctest0) */ - -#define SIOP_CTEST0_RES 0xfc -#define SIOP_CTEST0_RTRG 0x02 /* Real Target mode */ -#define SIOP_CTEST0_DDIR 0x01 /* Xfer direction (1-> from SCSI bus) */ - -/* Chip test register 1 (ctest1) */ - -#define SIOP_CTEST1_FMT 0xf0 /* Byte empty in DMA FIFO bottom (high->byte3) */ -#define SIOP_CTEST1_FFL 0x0f /* Byte full in DMA FIFO top, same */ - -/* Chip test register 2 (ctest2) */ - -#define SIOP_CTEST2_RES 0xc0 -#define SIOP_CTEST2_SOFF 0x20 /* Synch Offset compare (1-> zero Init, max Tgt */ -#define SIOP_CTEST2_SFP 0x10 /* SCSI FIFO Parity */ -#define SIOP_CTEST2_DFP 0x08 /* DMA FIFO Parity */ -#define SIOP_CTEST2_TEOP 0x04 /* True EOP (a-la 5380) */ -#define SIOP_CTEST2_DREQ 0x02 /* DREQ status */ -#define SIOP_CTEST2_DACK 0x01 /* DACK status */ - -/* Chip test register 3 (ctest3) read-only, top of SCSI FIFO */ - -/* Chip test register 4 (ctest4) */ - -#define SIOP_CTEST4_RES 0x80 -#define SIOP_CTEST4_ZMOD 0x40 /* High-impedance outputs */ -#define SIOP_CTEST4_SZM 0x20 /* ditto, SCSI "outputs" */ -#define SIOP_CTEST4_SLBE 0x10 /* SCSI loobpack enable */ -#define SIOP_CTEST4_SFWR 0x08 /* SCSI FIFO write enable (from sodl) */ -#define SIOP_CTEST4_FBL 0x07 /* DMA FIFO Byte Lane select (from ctest6) - 4->0, .. 7->3 */ - -/* Chip test register 5 (ctest5) */ - -#define SIOP_CTEST5_ADCK 0x80 /* Clock Address Incrementor */ -#define SIOP_CTEST5_BBCK 0x40 /* Clock Byte counter */ -#define SIOP_CTEST5_ROFF 0x20 /* Reset SCSI offset */ -#define SIOP_CTEST5_MASR 0x10 /* Master set/reset pulses (of bits 3-0) */ -#define SIOP_CTEST5_DDIR 0x08 /* (re)set internal DMA direction */ -#define SIOP_CTEST5_EOP 0x04 /* (re)set internal EOP */ -#define SIOP_CTEST5_DREQ 0x02 /* (re)set internal REQ */ -#define SIOP_CTEST5_DACK 0x01 /* (re)set internal ACK */ - -/* Chip test register 6 (ctest6) DMA FIFO access */ - -/* Chip test register 7 (ctest7) */ - -#define SIOP_CTEST7_RES 0xe0 -#define SIOP_CTEST7_STD 0x10 /* Disable selection timeout */ -#define SIOP_CTEST7_DFP 0x08 /* DMA FIFO parity bit */ -#define SIOP_CTEST7_EVP 0x04 /* Even parity (to host bus) */ -#define SIOP_CTEST7_DC 0x02 /* Drive DC pin low on SCRIPT fetches */ -#define SIOP_CTEST7_DIFF 0x01 /* Differential mode */ - -/* DMA FIFO register (dfifo) */ - -#define SIOP_DFIFO_FLF 0x80 /* Flush (spill) DMA FIFO */ -#define SIOP_DFIFO_CLF 0x40 /* Clear DMA and SCSI FIFOs */ -#define SIOP_DFIFO_BO 0x3f /* FIFO byte offset counter */ - -/* Interrupt status register (istat) */ - -#define SIOP_ISTAT_ABRT 0x80 /* Abort operation */ -#define SIOP_ISTAT_RES 0x70 -#define SIOP_ISTAT_CON 0x08 /* Connected */ -#define SIOP_ISTAT_PRE 0x04 /* Pointer register empty */ -#define SIOP_ISTAT_SIP 0x02 /* SCSI Interrupt pending */ -#define SIOP_ISTAT_DIP 0x01 /* DMA Interrupt pending */ - - -/* DMA Mode register (dmode) */ - -#define SIOP_DMODE_BL_MASK 0xc0 /* 0->1 1->2 2->4 3->8 */ -#define SIOP_DMODE_BW16 0x20 /* Bus Width is 16 bits */ -#define SIOP_DMODE_286 0x10 /* 286 mode */ -#define SIOP_DMODE_IO_M 0x08 /* xfer data to memory or I/O space */ -#define SIOP_DMODE_FAM 0x04 /* fixed address mode */ -#define SIOP_DMODE_PIPE 0x02 /* SCRIPTS in Pipeline mode */ -#define SIOP_DMODE_MAN 0x01 /* SCRIPTS in Manual start mode */ - -/* DMA interrupt enable register (dien) */ - -#define SIOP_DIEN_RES 0xe0 -#define SIOP_DIEN_ABRT 0x10 /* On Abort */ -#define SIOP_DIEN_SSI 0x08 /* On SCRIPTS sstep */ -#define SIOP_DIEN_SIR 0x04 /* On SCRIPTS intr instruction */ -#define SIOP_DIEN_WTD 0x02 /* On watchdog timeout */ -#define SIOP_DIEN_OPC 0x01 /* On SCRIPTS illegal opcode */ - -/* DMA control register (dcntl) */ - -#define SIOP_DCNTL_CF_MASK 0xc0 /* Clock frequency dividers: - 0 --> 37.51..50.00 Mhz, div=2 - 1 --> 25.01..37.50 Mhz, div=1.5 - 2 --> 16.67..25.00 Mhz, div=1 - 3 --> reserved - */ -#define SIOP_DCNTL_S16 0x20 /* SCRIPTS fetches 16bits at a time */ -#define SIOP_DCNTL_SSM 0x10 /* Single step mode */ -#define SIOP_DCNTL_LLM 0x08 /* Enable Low-level mode */ -#define SIOP_DCNTL_STD 0x04 /* Start SCRIPTS operation */ -#define SIOP_DCNTL_RES 0x02 -#define SIOP_DCNTL_RST 0x01 /* Software reset */ - diff --git a/scsi/adapters/scsi_53C700_hdw.c b/scsi/adapters/scsi_53C700_hdw.c deleted file mode 100644 index 61b5a3b..0000000 --- a/scsi/adapters/scsi_53C700_hdw.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ -/* - * File: scsi_53C700_hdw.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 8/91 - * - * Bottom layer of the SCSI driver: chip-dependent functions - * - * This file contains the code that is specific to the NCR 53C700 - * SCSI chip (Host Bus Adapter in SCSI parlance): probing, start - * operation, and interrupt routine. - */ - - -#include <siop.h> -#if NSIOP > 0 -#include <platforms.h> - -#include <mach/std_types.h> -#include <sys/types.h> -#include <chips/busses.h> -#include <scsi/compat_30.h> -#include <machine/machspl.h> - -#include <sys/syslog.h> - -#include <scsi/scsi.h> -#include <scsi/scsi2.h> -#include <scsi/scsi_defs.h> - -#include <scsi/adapters/scsi_53C700.h> - -#ifdef PAD -typedef struct { - volatile unsigned char siop_scntl0; /* rw: SCSI control reg 0 */ - PAD(pad0); - volatile unsigned char siop_scntl1; /* rw: SCSI control reg 1 */ - PAD(pad1); - volatile unsigned char siop_sdid; /* rw: SCSI Destination ID */ - PAD(pad2); - volatile unsigned char siop_sien; /* rw: SCSI Interrupt Enable */ - PAD(pad3); - volatile unsigned char siop_scid; /* rw: SCSI Chip ID reg */ - PAD(pad4); - volatile unsigned char siop_sxfer; /* rw: SCSI Transfer reg */ - PAD(pad5); - volatile unsigned char siop_sodl; /* rw: SCSI Output Data Latch */ - PAD(pad6); - volatile unsigned char siop_socl; /* rw: SCSI Output Control Latch */ - PAD(pad7); - volatile unsigned char siop_sfbr; /* ro: SCSI First Byte Received */ - PAD(pad8); - volatile unsigned char siop_sidl; /* ro: SCSI Input Data Latch */ - PAD(pad9); - volatile unsigned char siop_sbdl; /* ro: SCSI Bus Data Lines */ - PAD(pad10); - volatile unsigned char siop_sbcl; /* ro: SCSI Bus Control Lines */ - PAD(pad11); - volatile unsigned char siop_dstat; /* ro: DMA status */ - PAD(pad12); - volatile unsigned char siop_sstat0; /* ro: SCSI status reg 0 */ - PAD(pad13); - volatile unsigned char siop_sstat1; /* ro: SCSI status reg 1 */ - PAD(pad14); - volatile unsigned char siop_sstat2; /* ro: SCSI status reg 2 */ - PAD(pad15); - volatile unsigned char siop_res1; - PAD(pad16); - volatile unsigned char siop_res2; - PAD(pad17); - volatile unsigned char siop_res3; - PAD(pad18); - volatile unsigned char siop_res4; - PAD(pad19); - volatile unsigned char siop_ctest0; /* ro: Chip test register 0 */ - PAD(pad20); - volatile unsigned char siop_ctest1; /* ro: Chip test register 1 */ - PAD(pad21); - volatile unsigned char siop_ctest2; /* ro: Chip test register 2 */ - PAD(pad22); - volatile unsigned char siop_ctest3; /* ro: Chip test register 3 */ - PAD(pad23); - volatile unsigned char siop_ctest4; /* rw: Chip test register 4 */ - PAD(pad24); - volatile unsigned char siop_ctest5; /* rw: Chip test register 5 */ - PAD(pad25); - volatile unsigned char siop_ctest6; /* rw: Chip test register 6 */ - PAD(pad26); - volatile unsigned char siop_ctest7; /* rw: Chip test register 7 */ - PAD(pad27); - volatile unsigned char siop_temp0; /* rw: Temporary Stack reg */ - PAD(pad28); - volatile unsigned char siop_temp1; - PAD(pad29); - volatile unsigned char siop_temp2; - PAD(pad30); - volatile unsigned char siop_temp3; - PAD(pad31); - volatile unsigned char siop_dfifo; /* rw: DMA FIFO */ - PAD(pad32); - volatile unsigned char siop_istat; /* rw: Interrupt Status reg */ - PAD(pad33); - volatile unsigned char siop_res5; - PAD(pad34); - volatile unsigned char siop_res6; - PAD(pad35); - volatile unsigned char siop_dbc0; /* rw: DMA Byte Counter reg */ - PAD(pad36); - volatile unsigned char siop_dbc1; - PAD(pad37); - volatile unsigned char siop_dbc2; - PAD(pad38); - volatile unsigned char siop_dcmd; /* rw: DMA Command Register */ - PAD(pad39); - volatile unsigned char siop_dnad0; /* rw: DMA Next Address */ - PAD(pad40); - volatile unsigned char siop_dnad1; - PAD(pad41); - volatile unsigned char siop_dnad2; - PAD(pad42); - volatile unsigned char siop_dnad3; - PAD(pad43); - volatile unsigned char siop_dsp0; /* rw: DMA SCRIPTS Pointer reg */ - PAD(pad44); - volatile unsigned char siop_dsp1; - PAD(pad45); - volatile unsigned char siop_dsp2; - PAD(pad46); - volatile unsigned char siop_dsp3; - PAD(pad47); - volatile unsigned char siop_dsps0; /* rw: DMA SCRIPTS Pointer Save reg */ - PAD(pad48); - volatile unsigned char siop_dsps1; - PAD(pad49); - volatile unsigned char siop_dsps2; - PAD(pad50); - volatile unsigned char siop_dsps3; - PAD(pad51); - volatile unsigned char siop_dmode; /* rw: DMA Mode reg */ - PAD(pad52); - volatile unsigned char siop_res7; - PAD(pad53); - volatile unsigned char siop_res8; - PAD(pad54); - volatile unsigned char siop_res9; - PAD(pad55); - volatile unsigned char siop_res10; - PAD(pad56); - volatile unsigned char siop_dien; /* rw: DMA Interrupt Enable */ - PAD(pad57); - volatile unsigned char siop_dwt; /* rw: DMA Watchdog Timer */ - PAD(pad58); - volatile unsigned char siop_dcntl; /* rw: DMA Control reg */ - PAD(pad59); - volatile unsigned char siop_res11; - PAD(pad60); - volatile unsigned char siop_res12; - PAD(pad61); - volatile unsigned char siop_res13; - PAD(pad62); - volatile unsigned char siop_res14; - PAD(pad63); -} siop_padded_regmap_t; -#else -typedef siop_regmap_t siop_padded_regmap_t; -#endif - -/* - * Macros to make certain things a little more readable - */ - -/* forward decls */ - -int siop_reset_scsibus(); -boolean_t siop_probe_target(); - -/* - * State descriptor for this layer. There is one such structure - * per (enabled) 53C700 interface - */ -struct siop_softc { - watchdog_t wd; - siop_padded_regmap_t *regs; /* 53C700 registers */ - scsi_dma_ops_t *dma_ops; /* DMA operations and state */ - opaque_t dma_state; - - script_t script; - int (*error_handler)(); - int in_count; /* amnt we expect to receive */ - int out_count; /* amnt we are going to ship */ - - volatile char state; -#define SIOP_STATE_BUSY 0x01 /* selecting or currently connected */ -#define SIOP_STATE_TARGET 0x04 /* currently selected as target */ -#define SIOP_STATE_COLLISION 0x08 /* lost selection attempt */ -#define SIOP_STATE_DMA_IN 0x10 /* tgt --> initiator xfer */ - - unsigned char ntargets; /* how many alive on this scsibus */ - unsigned char done; - - scsi_softc_t *sc; - target_info_t *active_target; - - target_info_t *next_target; /* trying to seize bus */ - queue_head_t waiting_targets;/* other targets competing for bus */ - -} siop_softc_data[NSIOP]; - -typedef struct siop_softc *siop_softc_t; - -siop_softc_t siop_softc[NSIOP]; - -/* - * Definition of the controller for the auto-configuration program. - */ - -int siop_probe(), scsi_slave(), scsi_attach(), siop_go(), siop_intr(); - -caddr_t siop_std[NSIOP] = { 0 }; -struct bus_device *siop_dinfo[NSIOP*8]; -struct bus_ctlr *siop_minfo[NSIOP]; -struct bus_driver siop_driver = - { siop_probe, scsi_slave, scsi_attach, siop_go, siop_std, "rz", siop_dinfo, - "siop", siop_minfo, BUS_INTR_B4_PROBE}; - -/* - * Scripts - */ -struct script -siop_script_data_in[] = { -}, - -siop_script_data_out[] = { -}, - -siop_script_cmd[] = { -}, - -/* Synchronous transfer neg(oti)ation */ - -siop_script_try_synch[] = { -}, - -/* Disconnect sequence */ - -siop_script_disconnect[] = { -}; - - -#define DEBUG -#ifdef DEBUG - -siop_state(base) - vm_offset_t base; -{ - siop_padded_regmap_t *regs; -.... - return 0; -} -siop_target_state(tgt) - target_info_t *tgt; -{ - if (tgt == 0) - tgt = siop_softc[0]->active_target; - if (tgt == 0) - return 0; - db_printf("@x%x: fl %x dma %X+%x cmd %x@%X id %x per %x off %x ior %X ret %X\n", - tgt, - tgt->flags, tgt->dma_ptr, tgt->transient_state.dma_offset, tgt->cur_cmd, - tgt->cmd_ptr, tgt->target_id, tgt->sync_period, tgt->sync_offset, - tgt->ior, tgt->done); - if (tgt->flags & TGT_DISCONNECTED){ - script_t spt; - - spt = tgt->transient_state.script; - db_printf("disconnected at "); - db_printsym(spt,1); - db_printf(": %x ", spt->condition); - db_printsym(spt->action,1); - db_printf(", "); - db_printsym(tgt->transient_state.handler, 1); - db_printf("\n"); - } - - return 0; -} - -siop_all_targets(unit) -{ - int i; - target_info_t *tgt; - for (i = 0; i < 8; i++) { - tgt = siop_softc[unit]->sc->target[i]; - if (tgt) - siop_target_state(tgt); - } -} - -siop_script_state(unit) -{ - script_t spt = siop_softc[unit]->script; - - if (spt == 0) return 0; - db_printsym(spt,1); - db_printf(": %x ", spt->condition); - db_printsym(spt->action,1); - db_printf(", "); - db_printsym(siop_softc[unit]->error_handler, 1); - return 0; - -} - -#define PRINT(x) if (scsi_debug) printf x - -#define TRMAX 200 -int tr[TRMAX+3]; -int trpt, trpthi; -#define TR(x) tr[trpt++] = x -#define TRWRAP trpthi = trpt; trpt = 0; -#define TRCHECK if (trpt > TRMAX) {TRWRAP} - -#define TRACE - -#ifdef TRACE - -#define LOGSIZE 256 -int siop_logpt; -char siop_log[LOGSIZE]; - -#define MAXLOG_VALUE 0x24 -struct { - char *name; - unsigned int count; -} logtbl[MAXLOG_VALUE]; - -static LOG(e,f) - char *f; -{ - siop_log[siop_logpt++] = (e); - if (siop_logpt == LOGSIZE) siop_logpt = 0; - if ((e) < MAXLOG_VALUE) { - logtbl[(e)].name = (f); - logtbl[(e)].count++; - } -} - -siop_print_log(skip) - int skip; -{ - register int i, j; - register unsigned char c; - - for (i = 0, j = siop_logpt; i < LOGSIZE; i++) { - c = siop_log[j]; - if (++j == LOGSIZE) j = 0; - if (skip-- > 0) - continue; - if (c < MAXLOG_VALUE) - db_printf(" %s", logtbl[c].name); - else - db_printf("-%d", c & 0x7f); - } - db_printf("\n"); - return 0; -} - -siop_print_stat() -{ - register int i; - register char *p; - for (i = 0; i < MAXLOG_VALUE; i++) { - if (p = logtbl[i].name) - printf("%d %s\n", logtbl[i].count, p); - } -} - -#else /* TRACE */ -#define LOG(e,f) -#endif /* TRACE */ - -#else /* DEBUG */ -#define PRINT(x) -#define LOG(e,f) -#define TR(x) -#define TRCHECK -#define TRWRAP -#endif /* DEBUG */ - - -/* - * Probe/Slave/Attach functions - */ - -/* - * Probe routine: - * Should find out (a) if the controller is - * present and (b) which/where slaves are present. - * - * Implementation: - * Send an identify msg to each possible target on the bus - * except of course ourselves. - */ -siop_probe(reg, ui) - char *reg; - struct bus_ctlr *ui; -{ - int unit = ui->unit; - siop_softc_t siop = &siop_softc_data[unit]; - int target_id, i; - scsi_softc_t *sc; - register siop_padded_regmap_t *regs; - int s; - boolean_t did_banner = FALSE; - char *cmd_ptr; - static char *here = "siop_probe"; - - /* - * We are only called if the chip is there, - * but make sure anyways.. - */ - regs = (siop_padded_regmap_t *) (reg); - if (check_memory(regs, 0)) - return 0; - -#if notyet - /* Mappable version side */ - SIOP_probe(reg, ui); -#endif - - /* - * Initialize hw descriptor - */ - siop_softc[unit] = siop; - siop->regs = regs; - - if ((siop->dma_ops = (scsi_dma_ops_t *)siop_std[unit]) == 0) - /* use same as unit 0 if undefined */ - siop->dma_ops = (scsi_dma_ops_t *)siop_std[0]; - siop->dma_state = (*siop->dma_ops->init)(unit, reg); - - queue_init(&siop->waiting_targets); - - sc = scsi_master_alloc(unit, siop); - siop->sc = sc; - - sc->go = siop_go; - sc->probe = siop_probe_target; - sc->watchdog = scsi_watchdog; - siop->wd.reset = siop_reset_scsibus; - -#ifdef MACH_KERNEL - sc->max_dma_data = -1; /* unlimited */ -#else - sc->max_dma_data = scsi_per_target_virtual; -#endif - - /* - * Reset chip - */ - s = splbio(); - siop_reset(siop, TRUE); - - /* - * Our SCSI id on the bus. - */ - - sc->initiator_id = my_scsi_id(unit); - printf("%s%d: my SCSI id is %d", ui->name, unit, sc->initiator_id); - - /* - * For all possible targets, see if there is one and allocate - * a descriptor for it if it is there. - */ - for (target_id = 0; target_id < 8; target_id++) { - - register unsigned csr, dsr; - scsi_status_byte_t status; - - /* except of course ourselves */ - if (target_id == sc->initiator_id) - continue; - - ..... - - printf(",%s%d", did_banner++ ? " " : " target(s) at ", - target_id); - - ..... - - - /* - * Found a target - */ - siop->ntargets++; - { - register target_info_t *tgt; - - tgt = scsi_slave_alloc(unit, target_id, siop); - - tgt->cmd_ptr = ... - tgt->dma_ptr = ... -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - fdma_init(&tgt->fdma, scsi_per_target_virtual); -#endif /*MACH_KERNEL*/ - } - } - printf(".\n"); - - splx(s); - return 1; -} - -boolean_t -siop_probe_target(sc, tgt, ior) - scsi_softc_t *sc; - target_info_t *tgt; - io_req_t ior; -{ - siop_softc_t siop = siop_softc[sc->masterno]; - boolean_t newlywed; - - newlywed = (tgt->cmd_ptr == 0); - if (newlywed) { - /* desc was allocated afresh */ - - tgt->cmd_ptr = ... - tgt->dma_ptr = ... -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - fdma_init(&tgt->fdma, scsi_per_target_virtual); -#endif /*MACH_KERNEL*/ - - } - - if (scsi_inquiry(sc, tgt, SCSI_INQ_STD_DATA) == SCSI_RET_DEVICE_DOWN) - return FALSE; - - tgt->flags = TGT_ALIVE; - return TRUE; -} - - -static siop_wait(preg, until) - volatile unsigned char *preg; -{ - int timeo = 1000000; - while ((*preg & until) != until) { - delay(1); - if (!timeo--) { - printf("siop_wait TIMEO with x%x\n", *preg); - break; - } - } - return *preg; -} - - -siop_reset(siop, quickly) - siop_softc_t siop; - boolean_t quickly; -{ - register siop_padded_regmap_t *regs = siop->regs; - - .... - - if (quickly) - return; - - /* - * reset the scsi bus, the interrupt routine does the rest - * or you can call siop_bus_reset(). - */ - .... - -} - -/* - * Operational functions - */ - -/* - * Start a SCSI command on a target - */ -siop_go(sc, tgt, cmd_count, in_count, cmd_only) - scsi_softc_t *sc; - target_info_t *tgt; - boolean_t cmd_only; -{ - siop_softc_t siop; - register int s; - boolean_t disconn; - script_t scp; - boolean_t (*handler)(); - - LOG(1,"go"); - - siop = (siop_softc_t)tgt->hw_state; - - .... -} - -siop_attempt_selection(siop) - siop_softc_t siop; -{ - target_info_t *tgt; - register int out_count; - siop_padded_regmap_t *regs; - register int cmd; - boolean_t ok; - scsi_ret_t ret; - - regs = siop->regs; - tgt = siop->next_target; - - LOG(4,"select"); - LOG(0x80+tgt->target_id,0); - - /* - * Init bus state variables and set registers. - */ - siop->active_target = tgt; - - /* reselection pending ? */ - ...... -} - -/* - * Interrupt routine - * Take interrupts from the chip - * - * Implementation: - * Move along the current command's script if - * all is well, invoke error handler if not. - */ -siop_intr(unit) -{ - register siop_softc_t siop; - register script_t scp; - register unsigned csr, bs, cmd; - register siop_padded_regmap_t *regs; - boolean_t try_match; -#if notyet - extern boolean_t rz_use_mapped_interface; - - if (rz_use_mapped_interface) - return SIOP_intr(unit); -#endif - - LOG(5,"\n\tintr"); - - siop = siop_softc[unit]; - regs = siop->regs; - - /* ack interrupt */ - .... -} - - -siop_target_intr(siop) - register siop_softc_t siop; -{ - panic("SIOP: TARGET MODE !!!\n"); -} - -/* - * All the many little things that the interrupt - * routine might switch to - */ - -#endif /*NSIOP > 0*/ - diff --git a/scsi/adapters/scsi_53C94.h b/scsi/adapters/scsi_53C94.h deleted file mode 100644 index 82891f3..0000000 --- a/scsi/adapters/scsi_53C94.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_53C94.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 9/90 - * - * Defines for the NCR 53C94 ASC (SCSI interface) - * Some gotcha came from the "86C01/53C94 DMA lab work" written - * by Ken Stewart (NCR MED Logic Products Applications Engineer) - * courtesy of NCR. Thanks Ken ! - */ - -/* - * Register map - */ - -typedef struct { - volatile unsigned char asc_tc_lsb; /* rw: Transfer Counter LSB */ - volatile unsigned char asc_tc_msb; /* rw: Transfer Counter MSB */ - volatile unsigned char asc_fifo; /* rw: FIFO top */ - volatile unsigned char asc_cmd; /* rw: Command */ - volatile unsigned char asc_csr; /* r: Status */ -#define asc_dbus_id asc_csr /* w: Destination Bus ID */ - volatile unsigned char asc_intr; /* r: Interrupt */ -#define asc_sel_timo asc_intr /* w: (re)select timeout */ - volatile unsigned char asc_ss; /* r: Sequence Step */ -#define asc_syn_p asc_ss /* w: synchronous period */ - volatile unsigned char asc_flags; /* r: FIFO flags + seq step */ -#define asc_syn_o asc_flags /* w: synchronous offset */ - volatile unsigned char asc_cnfg1; /* rw: Configuration 1 */ - volatile unsigned char asc_ccf; /* w: Clock Conv. Factor */ - volatile unsigned char asc_test; /* w: Test Mode */ - volatile unsigned char asc_cnfg2; /* rw: Configuration 2 */ - volatile unsigned char asc_cnfg3; /* rw: Configuration 3 */ - volatile unsigned char asc_rfb; /* w: Reserve FIFO byte */ -} asc_regmap_t; - - -/* - * Transfer Count: access macros - * That a NOP is required after loading the dma counter - * I learned on the NCR test code. Sic. - */ - -#define ASC_TC_MAX 0x10000 - -#define ASC_TC_GET(ptr,val) \ - val = ((ptr)->asc_tc_lsb&0xff)|(((ptr)->asc_tc_msb&0xff)<<8) -#define ASC_TC_PUT(ptr,val) \ - (ptr)->asc_tc_lsb=(val); \ - (ptr)->asc_tc_msb=(val)>>8; mb(); \ - (ptr)->asc_cmd = ASC_CMD_NOP|ASC_CMD_DMA; - -/* - * FIFO register - */ - -#define ASC_FIFO_DEEP 16 - - -/* - * Command register (command codes) - */ - -#define ASC_CMD_DMA 0x80 - /* Miscellaneous */ -#define ASC_CMD_NOP 0x00 -#define ASC_CMD_FLUSH 0x01 -#define ASC_CMD_RESET 0x02 -#define ASC_CMD_BUS_RESET 0x03 - /* Initiator state */ -#define ASC_CMD_XFER_INFO 0x10 -#define ASC_CMD_I_COMPLETE 0x11 -#define ASC_CMD_MSG_ACPT 0x12 -#define ASC_CMD_XFER_PAD 0x18 -#define ASC_CMD_SET_ATN 0x1a -#define ASC_CMD_CLR_ATN 0x1b - /* Target state */ -#define ASC_CMD_SND_MSG 0x20 -#define ASC_CMD_SND_STATUS 0x21 -#define ASC_CMD_SND_DATA 0x22 -#define ASC_CMD_DISC_SEQ 0x23 -#define ASC_CMD_TERM 0x24 -#define ASC_CMD_T_COMPLETE 0x25 -#define ASC_CMD_DISC 0x27 -#define ASC_CMD_RCV_MSG 0x28 -#define ASC_CMD_RCV_CDB 0x29 -#define ASC_CMD_RCV_DATA 0x2a -#define ASC_CMD_RCV_CMD 0x2b -#define ASC_CMD_ABRT_DMA 0x04 - /* Disconnected state */ -#define ASC_CMD_RESELECT 0x40 -#define ASC_CMD_SEL 0x41 -#define ASC_CMD_SEL_ATN 0x42 -#define ASC_CMD_SEL_ATN_STOP 0x43 -#define ASC_CMD_ENABLE_SEL 0x44 -#define ASC_CMD_DISABLE_SEL 0x45 -#define ASC_CMD_SEL_ATN3 0x46 - -/* this is approximate (no ATN3) but good enough */ -#define asc_isa_select(cmd) (((cmd)&0x7c)==0x40) - -/* - * Status register, and phase encoding - */ - -#define ASC_CSR_INT 0x80 -#define ASC_CSR_GE 0x40 -#define ASC_CSR_PE 0x20 -#define ASC_CSR_TC 0x10 -#define ASC_CSR_VGC 0x08 -#define ASC_CSR_MSG 0x04 -#define ASC_CSR_CD 0x02 -#define ASC_CSR_IO 0x01 - -#define ASC_PHASE(csr) SCSI_PHASE(csr) - -/* - * Destination Bus ID - */ - -#define ASC_DEST_ID_MASK 0x07 - - -/* - * Interrupt register - */ - -#define ASC_INT_RESET 0x80 -#define ASC_INT_ILL 0x40 -#define ASC_INT_DISC 0x20 -#define ASC_INT_BS 0x10 -#define ASC_INT_FC 0x08 -#define ASC_INT_RESEL 0x04 -#define ASC_INT_SEL_ATN 0x02 -#define ASC_INT_SEL 0x01 - - -/* - * Timeout register: - * - * val = (timeout * CLK_freq) / (8192 * CCF); - */ - -#define asc_timeout_250(clk,ccf) ((31*clk)/ccf) - -/* - * Sequence Step register - */ - -#define ASC_SS_XXXX 0xf0 -#define ASC_SS_SOM 0x80 -#define ASC_SS_MASK 0x07 -#define ASC_SS(ss) ((ss)&ASC_SS_MASK) - -/* - * Synchronous Transfer Period - */ - -#define ASC_STP_MASK 0x1f -#define ASC_STP_MIN 0x05 /* 5 clk per byte */ -#define ASC_STP_MAX 0x04 /* after ovfl, 35 clk/byte */ - -/* - * FIFO flags - */ - -#define ASC_FLAGS_SEQ_STEP 0xe0 -#define ASC_FLAGS_FIFO_CNT 0x1f - -/* - * Synchronous offset - */ - -#define ASC_SYNO_MASK 0x0f /* 0 -> asyn */ - -/* - * Configuration 1 - */ - -#define ASC_CNFG1_SLOW 0x80 -#define ASC_CNFG1_SRD 0x40 -#define ASC_CNFG1_P_TEST 0x20 -#define ASC_CNFG1_P_CHECK 0x10 -#define ASC_CNFG1_TEST 0x08 -#define ASC_CNFG1_MY_BUS_ID 0x07 - -/* - * CCF register - */ - -#define ASC_CCF_10MHz 0x2 -#define ASC_CCF_15MHz 0x3 -#define ASC_CCF_20MHz 0x4 -#define ASC_CCF_25MHz 0x5 - -#define mhz_to_ccf(x) (((x-1)/5)+1) /* see specs for limits */ - -/* - * Test register - */ - -#define ASC_TEST_XXXX 0xf8 -#define ASC_TEST_HI_Z 0x04 -#define ASC_TEST_I 0x02 -#define ASC_TEST_T 0x01 - -/* - * Configuration 2 - */ - -#define ASC_CNFG2_RFB 0x80 -#define ASC_CNFG2_EPL 0x40 -#define ASC_CNFG2_EBC 0x20 -#define ASC_CNFG2_DREQ_HIZ 0x10 -#define ASC_CNFG2_SCSI2 0x08 -#define ASC_CNFG2_BPA 0x04 -#define ASC_CNFG2_RPE 0x02 -#define ASC_CNFG2_DPE 0x01 - -/* - * Configuration 3 - */ - -#define ASC_CNFG3_XXXX 0xf8 -#define ASC_CNFG3_SRB 0x04 -#define ASC_CNFG3_ALT_DMA 0x02 -#define ASC_CNFG3_T8 0x01 - diff --git a/scsi/adapters/scsi_53C94_hdw.c b/scsi/adapters/scsi_53C94_hdw.c deleted file mode 100644 index dad9b22..0000000 --- a/scsi/adapters/scsi_53C94_hdw.c +++ /dev/null @@ -1,2840 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1993,1992,1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS AS-IS - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_53C94_hdw.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 9/90 - * - * Bottom layer of the SCSI driver: chip-dependent functions - * - * This file contains the code that is specific to the NCR 53C94 - * SCSI chip (Host Bus Adapter in SCSI parlance): probing, start - * operation, and interrupt routine. - */ - -/* - * This layer works based on small simple 'scripts' that are installed - * at the start of the command and drive the chip to completion. - * The idea comes from the specs of the NCR 53C700 'script' processor. - * - * There are various reasons for this, mainly - * - Performance: identify the common (successful) path, and follow it; - * at interrupt time no code is needed to find the current status - * - Code size: it should be easy to compact common operations - * - Adaptability: the code skeleton should adapt to different chips without - * terrible complications. - * - Error handling: and it is easy to modify the actions performed - * by the scripts to cope with strange but well identified sequences - * - */ - -#include <asc.h> -#if NASC > 0 -#include <platforms.h> - -#ifdef DECSTATION -typedef unsigned char asc_register_t; -#define PAD(n) char n[3]; -#define mb() -#ifdef MACH_KERNEL -#define HAS_MAPPED_SCSI -#endif -#define ASC_PROBE_DYNAMICALLY FALSE /* established custom */ -#define DEBUG 1 -#define TRACE 1 -#endif - -#ifdef FLAMINGO -typedef unsigned int asc_register_t; -#define PAD(n) int n; /* sparse ! */ -#define mb() wbflush() /* memory barrier */ -#define ASC_PROBE_DYNAMICALLY TRUE -#define DEBUG 1 -#define TRACE 1 -#endif - -#include <mach/std_types.h> -#include <sys/types.h> -#include <chips/busses.h> -#include <scsi/compat_30.h> -#include <machine/machspl.h> - -#include <scsi/scsi.h> -#include <scsi/scsi2.h> - -#include <scsi/adapters/scsi_53C94.h> -#include <scsi/scsi_defs.h> -#include <scsi/adapters/scsi_dma.h> - -#define private static - -#ifdef PAD -typedef struct { - volatile asc_register_t asc_tc_lsb; /* rw: Transfer Counter LSB */ - PAD(pad0) - volatile asc_register_t asc_tc_msb; /* rw: Transfer Counter MSB */ - PAD(pad1) - volatile asc_register_t asc_fifo; /* rw: FIFO top */ - PAD(pad2) - volatile asc_register_t asc_cmd; /* rw: Command */ - PAD(pad3) - volatile asc_register_t asc_csr; /* r: Status */ -/*#define asc_dbus_id asc_csr /* w: Destination Bus ID */ - PAD(pad4) - volatile asc_register_t asc_intr; /* r: Interrupt */ -/*#define asc_sel_timo asc_intr /* w: (re)select timeout */ - PAD(pad5) - volatile asc_register_t asc_ss; /* r: Sequence Step */ -/*#define asc_syn_p asc_ss /* w: synchronous period */ - PAD(pad6) - volatile asc_register_t asc_flags; /* r: FIFO flags + seq step */ -/*#define asc_syn_o asc_flags /* w: synchronous offset */ - PAD(pad7) - volatile asc_register_t asc_cnfg1; /* rw: Configuration 1 */ - PAD(pad8) - volatile asc_register_t asc_ccf; /* w: Clock Conv. Factor */ - PAD(pad9) - volatile asc_register_t asc_test; /* w: Test Mode */ - PAD(pad10) - volatile asc_register_t asc_cnfg2; /* rw: Configuration 2 */ - PAD(pad11) - volatile asc_register_t asc_cnfg3; /* rw: Configuration 3 */ - PAD(pad12) - volatile asc_register_t asc_rfb; /* w: Reserve FIFO byte */ - PAD(pad13) -} asc_padded_regmap_t; - -#else /* !PAD */ - -typedef asc_regmap_t asc_padded_regmap_t; - -#endif /* !PAD */ - -#define get_reg(r,x) ((unsigned char)((r)->x)) - -#define fifo_count(r) ((r)->asc_flags & ASC_FLAGS_FIFO_CNT) -#define get_fifo(r) get_reg(r,asc_fifo) - -boolean_t asc_probe_dynamically = ASC_PROBE_DYNAMICALLY; - -/* - * We might need to use some fields usually - * handled by the DMA engine, if asked to. - * These are "dma_ptr" and "hba_dep". - */ -#define has_oddb hba_dep[0] -#define the_oddb hba_dep[1] - -/* - * A script has a three parts: a pre-condition, an action, and - * an optional command to the chip. The first triggers error - * handling if not satisfied and in our case it is a match - * of the expected and actual scsi-bus phases. - * The action part is just a function pointer, and the - * command is what the 53c90 should be told to do at the end - * of the action processing. This command is only issued and the - * script proceeds if the action routine returns TRUE. - * See asc_intr() for how and where this is all done. - */ - -typedef struct script { - unsigned char condition; /* expected state at interrupt */ - unsigned char command; /* command to the chip */ - unsigned short flags; /* unused padding */ - boolean_t (*action)(); /* extra operations */ -} *script_t; - -/* Matching on the condition value */ -#define ANY 0xff -#define SCRIPT_MATCH(csr,ir,value) ((SCSI_PHASE(csr)==(value)) || \ - (((value)==ANY) && \ - ((ir)&(ASC_INT_DISC|ASC_INT_FC)))) - -/* When no command is needed */ -#define SCRIPT_END -1 - -/* forward decls of script actions */ -boolean_t - asc_end(), /* all come to an end */ - asc_clean_fifo(), /* .. in preparation for status byte */ - asc_get_status(), /* get status from target */ - asc_put_status(), /* send status to initiator */ - asc_dma_in(), /* get data from target via dma */ - asc_dma_in_r(), /* get data from target via dma (restartable)*/ - asc_dma_out(), /* send data to target via dma */ - asc_dma_out_r(), /* send data to target via dma (restartable) */ - asc_dosynch(), /* negotiate synch xfer */ - asc_msg_in(), /* receive the disconenct message */ - asc_disconnected(), /* target has disconnected */ - asc_reconnect(); /* target reconnected */ - -/* forward decls of error handlers */ -boolean_t - asc_err_generic(), /* generic handler */ - asc_err_disconn(), /* target disconnects amidst */ - gimmeabreak(); /* drop into the debugger */ - -int asc_reset_scsibus(); -boolean_t asc_probe_target(); -private asc_wait(); - -/* - * State descriptor for this layer. There is one such structure - * per (enabled) SCSI-53c90 interface - */ -struct asc_softc { - watchdog_t wd; - asc_padded_regmap_t *regs; /* 53c90 registers */ - - scsi_dma_ops_t *dma_ops; /* DMA operations and state */ - opaque_t dma_state; - - script_t script; /* what should happen next */ - boolean_t (*error_handler)();/* what if something is wrong */ - int in_count; /* amnt we expect to receive */ - int out_count; /* amnt we are going to ship */ - - volatile char state; -#define ASC_STATE_BUSY 0x01 /* selecting or currently connected */ -#define ASC_STATE_TARGET 0x04 /* currently selected as target */ -#define ASC_STATE_COLLISION 0x08 /* lost selection attempt */ -#define ASC_STATE_DMA_IN 0x10 /* tgt --> initiator xfer */ -#define ASC_STATE_SPEC_DMA 0x20 /* special, 8 byte threshold dma */ -#define ASC_STATE_DO_RFB 0x40 /* DMA engine cannot handle odd bytes */ - - unsigned char ntargets; /* how many alive on this scsibus */ - unsigned char done; - unsigned char extra_count; /* sleazy trick to spare an interrupt */ - int dmacnt_at_end; - - scsi_softc_t *sc; /* HBA-indep info */ - target_info_t *active_target; /* the current one */ - - target_info_t *next_target; /* trying to seize bus */ - queue_head_t waiting_targets;/* other targets competing for bus */ - - unsigned char ss_was; /* districate powered on/off devices */ - unsigned char cmd_was; - - unsigned char timeout; /* cache a couple numbers */ - unsigned char ccf; - unsigned char clk; - -} asc_softc_data[NASC]; - -typedef struct asc_softc *asc_softc_t; - -asc_softc_t asc_softc[NASC]; - -/* - * Synch xfer parameters, and timing conversions - */ -int asc_min_period = 5; /* in CLKS/BYTE, e.g. 1 CLK = 40nsecs @25 Mhz */ -int asc_max_offset = 15; /* pure number */ - -int asc_to_scsi_period(a,clk) -{ - /* Note: the SCSI unit is 4ns, hence - A_P * 1,000,000,000 - ------------------- = S_P - C_Mhz * 4 - */ - return a * (250 / clk); - -} - -int scsi_period_to_asc(p,clk) -{ - register int ret; - - ret = (p * clk) / 250; - if (ret < asc_min_period) - return asc_min_period; - if ((asc_to_scsi_period(ret,clk)) < p) - return ret + 1; - return ret; -} - -#define readback(a) {register int foo; foo = a; mb();} - -#define u_min(a,b) (((a) < (b)) ? (a) : (b)) - -/* - * Definition of the controller for the auto-configuration program. - */ - -int asc_probe(), scsi_slave(), asc_go(), asc_intr(); -void scsi_attach(); - -vm_offset_t asc_std[NASC] = { 0 }; -struct bus_device *asc_dinfo[NASC*8]; -struct bus_ctlr *asc_minfo[NASC]; -struct bus_driver asc_driver = - { asc_probe, scsi_slave, scsi_attach, asc_go, asc_std, "rz", asc_dinfo, - "asc", asc_minfo, BUS_INTR_B4_PROBE}; - - -int asc_clock_speed_in_mhz[NASC] = {25,25,25,25}; /* original 3max */ - -asc_set_dmaops(unit, dmaops) - unsigned int unit; - scsi_dma_ops_t *dmaops; -{ - if (unit < NASC) - asc_std[unit] = (vm_offset_t)dmaops; -} - -/* - * Scripts - */ -struct script -asc_script_data_in[] = { /* started with SEL & DMA */ - {SCSI_PHASE_DATAI, ASC_CMD_XFER_INFO|ASC_CMD_DMA, 0, asc_dma_in}, - {SCSI_PHASE_STATUS, ASC_CMD_I_COMPLETE, 0, asc_clean_fifo}, - {SCSI_PHASE_MSG_IN, ASC_CMD_MSG_ACPT, 0, asc_get_status}, - {ANY, SCRIPT_END, 0, asc_end} -}, - -asc_script_data_out[] = { /* started with SEL & DMA */ - {SCSI_PHASE_DATAO, ASC_CMD_XFER_INFO|ASC_CMD_DMA, 0, asc_dma_out}, - {SCSI_PHASE_STATUS, ASC_CMD_I_COMPLETE, 0, asc_clean_fifo}, - {SCSI_PHASE_MSG_IN, ASC_CMD_MSG_ACPT, 0, asc_get_status}, - {ANY, SCRIPT_END, 0, asc_end} -}, - -asc_script_try_synch[] = { - {SCSI_PHASE_MSG_OUT, ASC_CMD_I_COMPLETE,0, asc_dosynch}, - {SCSI_PHASE_MSG_IN, ASC_CMD_MSG_ACPT, 0, asc_get_status}, - {ANY, SCRIPT_END, 0, asc_end} -}, - -asc_script_simple_cmd[] = { - {SCSI_PHASE_STATUS, ASC_CMD_I_COMPLETE, 0, asc_clean_fifo}, - {SCSI_PHASE_MSG_IN, ASC_CMD_MSG_ACPT, 0, asc_get_status}, - {ANY, SCRIPT_END, 0, asc_end} -}, - -asc_script_disconnect[] = { - {ANY, ASC_CMD_ENABLE_SEL, 0, asc_disconnected}, -/**/ {SCSI_PHASE_MSG_IN, ASC_CMD_MSG_ACPT, 0, asc_reconnect} -}, - -asc_script_restart_data_in[] = { /* starts after disconnect */ - {SCSI_PHASE_DATAI, ASC_CMD_XFER_INFO|ASC_CMD_DMA, 0, asc_dma_in_r}, - {SCSI_PHASE_STATUS, ASC_CMD_I_COMPLETE, 0, asc_clean_fifo}, - {SCSI_PHASE_MSG_IN, ASC_CMD_MSG_ACPT, 0, asc_get_status}, - {ANY, SCRIPT_END, 0, asc_end} -}, - -asc_script_restart_data_out[] = { /* starts after disconnect */ - {SCSI_PHASE_DATAO, ASC_CMD_XFER_INFO|ASC_CMD_DMA, 0, asc_dma_out_r}, - {SCSI_PHASE_STATUS, ASC_CMD_I_COMPLETE, 0, asc_clean_fifo}, - {SCSI_PHASE_MSG_IN, ASC_CMD_MSG_ACPT, 0, asc_get_status}, - {ANY, SCRIPT_END, 0, asc_end} -}, - -#if documentation -/* - * This is what might happen during a read - * that disconnects - */ -asc_script_data_in_wd[] = { /* started with SEL & DMA & allow disconnect */ - {SCSI_PHASE_MSG_IN, ASC_CMD_XFER_INFO|ASC_CMD_DMA, 0, asc_msg_in}, - {ANY, ASC_CMD_ENABLE_SEL, 0, asc_disconnected}, - {SCSI_PHASE_MSG_IN, ASC_CMD_MSG_ACPT, 0, asc_reconnect}, - {SCSI_PHASE_DATAI, ASC_CMD_XFER_INFO|ASC_CMD_DMA, 0, asc_dma_in}, - {SCSI_PHASE_STATUS, ASC_CMD_I_COMPLETE, 0, asc_clean_fifo}, - {SCSI_PHASE_MSG_IN, ASC_CMD_MSG_ACPT, 0, asc_get_status}, - {ANY, SCRIPT_END, 0, asc_end} -}, -#endif - -/* - * Target mode scripts - */ -asc_script_t_data_in[] = { - {SCSI_PHASE_CMD, ASC_CMD_RCV_DATA|ASC_CMD_DMA, 0, asc_dma_in_r}, - {SCSI_PHASE_DATAO, ASC_CMD_TERM, 0, asc_put_status}, - {ANY, SCRIPT_END, 0, asc_end} -}, - -asc_script_t_data_out[] = { - {SCSI_PHASE_CMD, ASC_CMD_SND_DATA|ASC_CMD_DMA, 0, asc_dma_out_r}, - {SCSI_PHASE_DATAI, ASC_CMD_TERM, 0, asc_put_status}, - {ANY, SCRIPT_END, 0, asc_end} -}; - - -#ifdef DEBUG - -#define PRINT(x) if (scsi_debug) printf x - -asc_state(regs) - asc_padded_regmap_t *regs; -{ - register unsigned char ff,csr,ir,d0,d1,cmd; - - if (regs == 0) { - if (asc_softc[0]) - regs = asc_softc[0]->regs; - else - regs = (asc_padded_regmap_t*)0xbf400000; - } - ff = get_reg(regs,asc_flags); - csr = get_reg(regs,asc_csr); -/* ir = get_reg(regs,asc_intr); nope, clears interrupt */ - d0 = get_reg(regs,asc_tc_lsb); - d1 = get_reg(regs,asc_tc_msb); - cmd = get_reg(regs,asc_cmd); - printf("dma %x ff %x csr %x cmd %x\n", - (d1 << 8) | d0, ff, csr, cmd); - return 0; -} - -asc_target_state(tgt) - target_info_t *tgt; -{ - if (tgt == 0) - tgt = asc_softc[0]->active_target; - if (tgt == 0) - return 0; - db_printf("@x%x: fl %x dma %X+%x cmd %x@%X id %x per %x off %x ior %X ret %X\n", - tgt, - tgt->flags, tgt->dma_ptr, tgt->transient_state.dma_offset, tgt->cur_cmd, - tgt->cmd_ptr, (long)tgt->target_id, - (long)tgt->sync_period, (long)tgt->sync_offset, - tgt->ior, (long)tgt->done); - if (tgt->flags & TGT_DISCONNECTED){ - script_t spt; - - spt = tgt->transient_state.script; - db_printf("disconnected at "); - db_printsym(spt,1); - db_printf(": %x %x ", spt->condition, spt->command); - db_printsym(spt->action,1); - db_printf(", "); - db_printsym(tgt->transient_state.handler, 1); - db_printf("\n"); - } - - return 0; -} - -asc_all_targets(unit) -{ - int i; - target_info_t *tgt; - for (i = 0; i < 8; i++) { - tgt = asc_softc[unit]->sc->target[i]; - if (tgt) - asc_target_state(tgt); - } -} - -asc_script_state(unit) -{ - script_t spt = asc_softc[unit]->script; - - if (spt == 0) return 0; - db_printsym(spt,1); - db_printf(": %x %x ", spt->condition, spt->command); - db_printsym(spt->action,1); - db_printf(", "); - db_printsym(asc_softc[unit]->error_handler, 1); - return 0; -} - -#define TRMAX 200 -int tr[TRMAX+3]; -int trpt, trpthi; -#define TR(x) tr[trpt++] = x -#define TRWRAP trpthi = trpt; trpt = 0; -#define TRCHECK if (trpt > TRMAX) {TRWRAP} - - -#ifdef TRACE - -#define LOGSIZE 256 -int asc_logpt; -char asc_log[LOGSIZE]; - -#define MAXLOG_VALUE 0x42 -struct { - char *name; - unsigned int count; -} logtbl[MAXLOG_VALUE]; - -/* private */ LOG(e,f) - char *f; -{ - asc_log[asc_logpt++] = (e); - if (asc_logpt == LOGSIZE) asc_logpt = 0; - if ((e) < MAXLOG_VALUE) { - logtbl[(e)].name = (f); - logtbl[(e)].count++; - } -} - -asc_print_log(skip) - int skip; -{ - register int i, j; - register unsigned char c; - - for (i = 0, j = asc_logpt; i < LOGSIZE; i++) { - c = asc_log[j]; - if (++j == LOGSIZE) j = 0; - if (skip-- > 0) - continue; - if (c < MAXLOG_VALUE) - db_printf(" %s", logtbl[c].name); - else - db_printf("-x%x", c & 0x7f); - } -} - -asc_print_stat() -{ - register int i; - register char *p; - for (i = 0; i < MAXLOG_VALUE; i++) { - if (p = logtbl[i].name) - printf("%d %s\n", logtbl[i].count, p); - } -} - -#else /*TRACE*/ -#define LOG(e,f) -#define LOGSIZE -#endif /*TRACE*/ - -#else /*DEBUG*/ -#define PRINT(x) -#define LOG(e,f) -#define LOGSIZE -#define TR(x) -#define TRCHECK -#define TRWRAP - -#endif /*DEBUG*/ - - -/* - * Probe/Slave/Attach functions - */ - -/* - * Probe routine: - * Should find out (a) if the controller is - * present and (b) which/where slaves are present. - * - * Implementation: - * Send a test-unit-ready to each possible target on the bus - * except of course ourselves. - */ -asc_probe(reg, ui) - vm_offset_t reg; - struct bus_ctlr *ui; -{ - int unit = ui->unit; - asc_softc_t asc = &asc_softc_data[unit]; - int target_id; - scsi_softc_t *sc; - register asc_padded_regmap_t *regs; - spl_t s; - boolean_t did_banner = FALSE; - - /* - * We are only called if the right board is there, - * but make sure anyways.. - */ - if (check_memory(reg, 0)) - return 0; - -#if defined(HAS_MAPPED_SCSI) - /* Mappable version side */ - ASC_probe(reg, ui); -#endif - - /* - * Initialize hw descriptor, cache some pointers - */ - asc_softc[unit] = asc; - asc->regs = (asc_padded_regmap_t *) (reg); - - if ((asc->dma_ops = (scsi_dma_ops_t *)asc_std[unit]) == 0) - /* use same as unit 0 if undefined */ - asc->dma_ops = (scsi_dma_ops_t *)asc_std[0]; - { - int dma_bsize = 16; /* bits, preferred */ - boolean_t do_rfb = FALSE; - - asc->dma_state = (*asc->dma_ops->init)(unit, reg, &dma_bsize, &do_rfb); - if (dma_bsize > 16) - asc->state |= ASC_STATE_SPEC_DMA; - if (do_rfb) - asc->state |= ASC_STATE_DO_RFB; - } - - queue_init(&asc->waiting_targets); - - asc->clk = asc_clock_speed_in_mhz[unit]; - asc->ccf = mhz_to_ccf(asc->clk); /* see .h file */ - asc->timeout = asc_timeout_250(asc->clk,asc->ccf); - - sc = scsi_master_alloc(unit, asc); - asc->sc = sc; - - sc->go = asc_go; - sc->watchdog = scsi_watchdog; - sc->probe = asc_probe_target; - asc->wd.reset = asc_reset_scsibus; - -#ifdef MACH_KERNEL - sc->max_dma_data = -1; -#else - sc->max_dma_data = scsi_per_target_virtual; -#endif - - regs = asc->regs; - - /* - * Our SCSI id on the bus. - * The user can set this via the prom on 3maxen/pmaxen. - * If this changes it is easy to fix: make a default that - * can be changed as boot arg. - */ - { - register unsigned char my_id; - - my_id = scsi_initiator_id[unit] & 0x7; - if (my_id != 7) - regs->asc_cnfg1 = my_id; mb(); - } - - /* - * Reset chip, fully. Note that interrupts are already enabled. - */ - s = splbio(); - asc_reset(asc, TRUE, asc->state & ASC_STATE_SPEC_DMA); - - sc->initiator_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID; - printf("%s%d: SCSI id %d", ui->name, unit, sc->initiator_id); - - { - register target_info_t *tgt; - - tgt = scsi_slave_alloc(sc->masterno, sc->initiator_id, asc); - (*asc->dma_ops->new_target)(asc->dma_state, tgt); - sccpu_new_initiator(tgt, tgt); - } - - if (asc_probe_dynamically) - printf("%s", ", will probe targets on demand"); - else { - - /* - * For all possible targets, see if there is one and allocate - * a descriptor for it if it is there. - */ - for (target_id = 0; target_id < 8; target_id++) { - register unsigned char csr, ss, ir, ff; - register scsi_status_byte_t status; - - /* except of course ourselves */ - if (target_id == sc->initiator_id) - continue; - - regs->asc_cmd = ASC_CMD_FLUSH; /* empty fifo */ - mb(); - delay(2); - - regs->asc_dbus_id = target_id; mb(); - regs->asc_sel_timo = asc->timeout; mb(); - - /* - * See if the unit is ready. - * XXX SHOULD inquiry LUN 0 instead !!! - */ - regs->asc_fifo = SCSI_CMD_TEST_UNIT_READY; mb(); - regs->asc_fifo = 0; mb(); - regs->asc_fifo = 0; mb(); - regs->asc_fifo = 0; mb(); - regs->asc_fifo = 0; mb(); - regs->asc_fifo = 0; mb(); - - /* select and send it */ - regs->asc_cmd = ASC_CMD_SEL; mb(); - - /* wait for the chip to complete, or timeout */ - csr = asc_wait(regs, ASC_CSR_INT, 1); - ss = get_reg(regs,asc_ss); - ir = get_reg(regs,asc_intr); - - /* empty fifo, there is garbage in it if timeout */ - regs->asc_cmd = ASC_CMD_FLUSH; mb(); - delay(2); - - /* - * Check if the select timed out - */ - if ((ASC_SS(ss) == 0) && (ir == ASC_INT_DISC)) - /* noone out there */ - continue; - - if (SCSI_PHASE(csr) != SCSI_PHASE_STATUS) { - printf( " %s%d%s", "ignoring target at ", target_id, - " cuz it acts weirdo"); - continue; - } - - printf(",%s%d", did_banner++ ? " " : " target(s) at ", - target_id); - - regs->asc_cmd = ASC_CMD_I_COMPLETE; - wbflush(); - csr = asc_wait(regs, ASC_CSR_INT, 1); - ir = get_reg(regs,asc_intr); /* ack intr */ - mb(); - - status.bits = get_fifo(regs); /* empty fifo */ - mb(); - ff = get_fifo(regs); - - if (status.st.scsi_status_code != SCSI_ST_GOOD) - scsi_error( 0, SCSI_ERR_STATUS, status.bits, 0); - - regs->asc_cmd = ASC_CMD_MSG_ACPT; mb(); - csr = asc_wait(regs, ASC_CSR_INT, 1); - ir = get_reg(regs,asc_intr); /* ack intr */ - mb(); - - /* - * Found a target - */ - asc->ntargets++; - { - register target_info_t *tgt; - tgt = scsi_slave_alloc(sc->masterno, target_id, asc); - - (*asc->dma_ops->new_target)(asc->dma_state, tgt); - } - } - } /* asc_probe_dynamically */ - - regs->asc_cmd = ASC_CMD_ENABLE_SEL; mb(); - - printf(".\n"); - - splx(s); - return 1; -} - -boolean_t -asc_probe_target(tgt, ior) - target_info_t *tgt; - io_req_t ior; -{ - asc_softc_t asc = asc_softc[tgt->masterno]; - boolean_t newlywed; - - newlywed = (tgt->cmd_ptr == 0); - if (newlywed) { - (*asc->dma_ops->new_target)(asc->dma_state, tgt); - } - - if (scsi_inquiry(tgt, SCSI_INQ_STD_DATA) == SCSI_RET_DEVICE_DOWN) - return FALSE; - - asc->ntargets++; - tgt->flags = TGT_ALIVE; - return TRUE; -} - -private asc_wait(regs, until, complain) - asc_padded_regmap_t *regs; -{ - int timeo = 1000000; - while ((regs->asc_csr & until) == 0) { - mb(); - delay(1); - if (!timeo--) { - if (complain) - printf("asc_wait TIMEO with x%x\n", get_reg(regs,asc_csr)); - break; - } - } - return get_reg(regs,asc_csr); -} - -asc_reset(asc, quick, special_dma) - asc_softc_t asc; -{ - char my_id; - int ccf; - asc_padded_regmap_t *regs; - - regs = asc->regs; - - /* preserve our ID for now */ - my_id = (regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID); - - /* - * Reset chip and wait till done - */ - regs->asc_cmd = ASC_CMD_RESET; - wbflush(); delay(25); - - /* spec says this is needed after reset */ - regs->asc_cmd = ASC_CMD_NOP; - wbflush(); delay(25); - - /* - * Set up various chip parameters - */ - regs->asc_ccf = asc->ccf; - wbflush(); - delay(25); - regs->asc_sel_timo = asc->timeout; mb(); - /* restore our ID */ - regs->asc_cnfg1 = my_id | ASC_CNFG1_P_CHECK; mb(); - regs->asc_cnfg2 = ASC_CNFG2_SCSI2; - mb(); - regs->asc_cnfg3 = special_dma ? (ASC_CNFG3_T8|ASC_CNFG3_ALT_DMA) : 0; - mb(); - /* zero anything else */ - ASC_TC_PUT(regs, 0); mb(); - regs->asc_syn_p = asc_min_period; mb(); - regs->asc_syn_o = 0; mb(); /* asynch for now */ - - regs->asc_cmd = ASC_CMD_ENABLE_SEL; mb(); - - if (quick) return; - - /* - * reset the scsi bus, the interrupt routine does the rest - * or you can call asc_bus_reset(). - */ - regs->asc_cmd = ASC_CMD_BUS_RESET; mb(); -} - - -/* - * Operational functions - */ - -/* - * Start a SCSI command on a target - */ -asc_go(tgt, cmd_count, in_count, cmd_only) - target_info_t *tgt; - boolean_t cmd_only; -{ - asc_softc_t asc; - register spl_t s; - boolean_t disconn; - script_t scp; - boolean_t (*handler)(); - - LOG(1,"go"); - - asc = (asc_softc_t)tgt->hw_state; - - tgt->transient_state.cmd_count = cmd_count; /* keep it here */ - tgt->transient_state.out_count = 0; /* default */ - - (*asc->dma_ops->map)(asc->dma_state, tgt); - - disconn = BGET(scsi_might_disconnect,tgt->masterno,tgt->target_id); - disconn = disconn && (asc->ntargets > 1); - disconn |= BGET(scsi_should_disconnect,tgt->masterno,tgt->target_id); - - /* - * Setup target state - */ - tgt->done = SCSI_RET_IN_PROGRESS; - - handler = (disconn) ? asc_err_disconn : asc_err_generic; - - switch (tgt->cur_cmd) { - case SCSI_CMD_READ: - case SCSI_CMD_LONG_READ: - LOG(2,"readop"); - scp = asc_script_data_in; - break; - case SCSI_CMD_WRITE: - case SCSI_CMD_LONG_WRITE: - LOG(0x18,"writeop"); - scp = asc_script_data_out; - break; - case SCSI_CMD_INQUIRY: - /* This is likely the first thing out: - do the synch neg if so */ - if (!cmd_only && ((tgt->flags&TGT_DID_SYNCH)==0)) { - scp = asc_script_try_synch; - tgt->flags |= TGT_TRY_SYNCH; - disconn = FALSE; - break; - } - case SCSI_CMD_REQUEST_SENSE: - case SCSI_CMD_MODE_SENSE: - case SCSI_CMD_RECEIVE_DIAG_RESULTS: - case SCSI_CMD_READ_CAPACITY: - case SCSI_CMD_READ_BLOCK_LIMITS: - case SCSI_CMD_READ_TOC: - case SCSI_CMD_READ_SUBCH: - case SCSI_CMD_READ_HEADER: - case 0xc4: /* despised: SCSI_CMD_DEC_PLAYBACK_STATUS */ - case 0xdd: /* despised: SCSI_CMD_NEC_READ_SUBCH_Q */ - case 0xde: /* despised: SCSI_CMD_NEC_READ_TOC */ - scp = asc_script_data_in; - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - case SCSI_CMD_MODE_SELECT: - case SCSI_CMD_REASSIGN_BLOCKS: - case SCSI_CMD_FORMAT_UNIT: - case 0xc9: /* vendor-spec: SCSI_CMD_DEC_PLAYBACK_CONTROL */ - tgt->transient_state.cmd_count = sizeof_scsi_command(tgt->cur_cmd); - tgt->transient_state.out_count = - cmd_count - tgt->transient_state.cmd_count; - scp = asc_script_data_out; - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - case SCSI_CMD_TEST_UNIT_READY: - /* - * Do the synch negotiation here, unless prohibited - * or done already - */ - if (tgt->flags & TGT_DID_SYNCH) { - scp = asc_script_simple_cmd; - } else { - scp = asc_script_try_synch; - tgt->flags |= TGT_TRY_SYNCH; - cmd_only = FALSE; - disconn = FALSE; - } - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - default: - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - scp = asc_script_simple_cmd; - } - - tgt->transient_state.script = scp; - tgt->transient_state.handler = handler; - tgt->transient_state.identify = (cmd_only) ? 0xff : - (disconn ? SCSI_IDENTIFY|SCSI_IFY_ENABLE_DISCONNECT : - SCSI_IDENTIFY); - - if (in_count) - tgt->transient_state.in_count = - (in_count < tgt->block_size) ? tgt->block_size : in_count; - else - tgt->transient_state.in_count = 0; - - /* - * See if another target is currently selected on - * this SCSI bus, e.g. lock the asc structure. - * Note that it is the strategy routine's job - * to serialize ops on the same target as appropriate. - * XXX here and everywhere, locks! - */ - /* - * Protection viz reconnections makes it tricky. - */ - s = splbio(); - - if (asc->wd.nactive++ == 0) - asc->wd.watchdog_state = SCSI_WD_ACTIVE; - - if (asc->state & ASC_STATE_BUSY) { - /* - * Queue up this target, note that this takes care - * of proper FIFO scheduling of the scsi-bus. - */ - LOG(3,"enqueue"); - enqueue_tail(&asc->waiting_targets, (queue_entry_t) tgt); - } else { - /* - * It is down to at most two contenders now, - * we will treat reconnections same as selections - * and let the scsi-bus arbitration process decide. - */ - asc->state |= ASC_STATE_BUSY; - asc->next_target = tgt; - asc_attempt_selection(asc); - /* - * Note that we might still lose arbitration.. - */ - } - splx(s); -} - -asc_attempt_selection(asc) - asc_softc_t asc; -{ - target_info_t *tgt; - asc_padded_regmap_t *regs; - register int out_count; - - regs = asc->regs; - tgt = asc->next_target; - - LOG(4,"select"); - LOG(0x80+tgt->target_id,0); - - /* - * We own the bus now.. unless we lose arbitration - */ - asc->active_target = tgt; - - /* Try to avoid reselect collisions */ - if ((regs->asc_csr & (ASC_CSR_INT|SCSI_PHASE_MSG_IN)) == - (ASC_CSR_INT|SCSI_PHASE_MSG_IN)) - return; - - /* - * Cleanup the FIFO - */ - regs->asc_cmd = ASC_CMD_FLUSH; - readback(regs->asc_cmd); - /* - * This value is not from spec, I have seen it failing - * without this delay and with logging disabled. That had - * about 42 extra instructions @25Mhz. - */ - delay(2);/* XXX time & move later */ - - - /* - * Init bus state variables - */ - asc->script = tgt->transient_state.script; - asc->error_handler = tgt->transient_state.handler; - asc->done = SCSI_RET_IN_PROGRESS; - - asc->out_count = 0; - asc->in_count = 0; - asc->extra_count = 0; - - /* - * Start the chip going - */ - out_count = (*asc->dma_ops->start_cmd)(asc->dma_state, tgt); - if (tgt->transient_state.identify != 0xff) { - regs->asc_fifo = tgt->transient_state.identify | tgt->lun; - mb(); - } - ASC_TC_PUT(regs, out_count); - readback(regs->asc_cmd); - - regs->asc_dbus_id = tgt->target_id; - readback(regs->asc_dbus_id); - - regs->asc_sel_timo = asc->timeout; - readback(regs->asc_sel_timo); - - regs->asc_syn_p = tgt->sync_period; - readback(regs->asc_syn_p); - - regs->asc_syn_o = tgt->sync_offset; - readback(regs->asc_syn_o); - - /* ugly little help for compiler */ -#define command out_count - if (tgt->flags & TGT_DID_SYNCH) { - command = (tgt->transient_state.identify == 0xff) ? - ASC_CMD_SEL | ASC_CMD_DMA : - ASC_CMD_SEL_ATN | ASC_CMD_DMA; /*preferred*/ - } else if (tgt->flags & TGT_TRY_SYNCH) - command = ASC_CMD_SEL_ATN_STOP; - else - command = ASC_CMD_SEL | ASC_CMD_DMA; - - /* Try to avoid reselect collisions */ - if ((regs->asc_csr & (ASC_CSR_INT|SCSI_PHASE_MSG_IN)) != - (ASC_CSR_INT|SCSI_PHASE_MSG_IN)) { - register int tmp; - - regs->asc_cmd = command; mb(); - /* - * Very nasty but infrequent problem here. We got/will get - * reconnected but the chip did not interrupt. The watchdog would - * fix it allright, but it stops the machine before it expires! - * Too bad we cannot just look at the interrupt register, sigh. - */ - tmp = get_reg(regs,asc_cmd); - if ((tmp != command) && (tmp == (ASC_CMD_NOP|ASC_CMD_DMA))) { - if ((regs->asc_csr & ASC_CSR_INT) == 0) { - delay(250); /* increase if in trouble */ - - if (get_reg(regs,asc_csr) == SCSI_PHASE_MSG_IN) { - /* ok, take the risk of reading the ir */ - tmp = get_reg(regs,asc_intr); mb(); - if (tmp & ASC_INT_RESEL) { - (void) asc_reconnect(asc, get_reg(regs,asc_csr), tmp); - asc_wait(regs, ASC_CSR_INT, 1); - tmp = get_reg(regs,asc_intr); mb(); - regs->asc_cmd = ASC_CMD_MSG_ACPT; - readback(regs->asc_cmd); - } else /* does not happen, but who knows.. */ - asc_reset(asc,FALSE,asc->state & ASC_STATE_SPEC_DMA); - } - } - } - } -#undef command -} - -/* - * Interrupt routine - * Take interrupts from the chip - * - * Implementation: - * Move along the current command's script if - * all is well, invoke error handler if not. - */ -asc_intr(unit, spllevel) - spl_t spllevel; -{ - register asc_softc_t asc; - register script_t scp; - register int ir, csr; - register asc_padded_regmap_t *regs; -#if defined(HAS_MAPPED_SCSI) - extern boolean_t rz_use_mapped_interface; - - if (rz_use_mapped_interface) - return ASC_intr(unit,spllevel); -#endif - - asc = asc_softc[unit]; - - LOG(5,"\n\tintr"); - /* collect ephemeral information */ - regs = asc->regs; - csr = get_reg(regs,asc_csr); mb(); - asc->ss_was = get_reg(regs,asc_ss); mb(); - asc->cmd_was = get_reg(regs,asc_cmd); mb(); - - /* drop spurious interrupts */ - if ((csr & ASC_CSR_INT) == 0) - return; - - ir = get_reg(regs,asc_intr); /* this re-latches CSR (and SSTEP) */ - mb(); - -TR(csr);TR(ir);TR(get_reg(regs,asc_cmd));TRCHECK - - /* this must be done within 250msec of disconnect */ - if (ir & ASC_INT_DISC) { - regs->asc_cmd = ASC_CMD_ENABLE_SEL; - readback(regs->asc_cmd); - } - - if (ir & ASC_INT_RESET) - return asc_bus_reset(asc); - - /* we got an interrupt allright */ - if (asc->active_target) - asc->wd.watchdog_state = SCSI_WD_ACTIVE; - -#if mips - splx(spllevel); /* drop priority */ -#endif - - if ((asc->state & ASC_STATE_TARGET) || - (ir & (ASC_INT_SEL|ASC_INT_SEL_ATN))) - return asc_target_intr(asc, csr, ir); - - /* - * In attempt_selection() we could not check the asc_intr - * register to see if a reselection was in progress [else - * we would cancel the interrupt, and it would not be safe - * anyways]. So we gave the select command even if sometimes - * the chip might have been reconnected already. What - * happens then is that we get an illegal command interrupt, - * which is why the second clause. Sorry, I'd do it better - * if I knew of a better way. - */ - if ((ir & ASC_INT_RESEL) || - ((ir & ASC_INT_ILL) && (regs->asc_cmd & ASC_CMD_SEL_ATN))) - return asc_reconnect(asc, csr, ir); - - /* - * Check for various errors - */ - if ((csr & (ASC_CSR_GE|ASC_CSR_PE)) || (ir & ASC_INT_ILL)) { - char *msg; -printf("{E%x,%x}", csr, ir); - if (csr & ASC_CSR_GE) - return;/* sit and prey? */ - - if (csr & ASC_CSR_PE) - msg = "SCSI bus parity error"; - if (ir & ASC_INT_ILL) - msg = "Chip sez Illegal Command"; - /* all we can do is to throw a reset on the bus */ - printf( "asc%d: %s%s", asc - asc_softc_data, msg, - ", attempting recovery.\n"); - asc_reset(asc, FALSE, asc->state & ASC_STATE_SPEC_DMA); - return; - } - - if ((scp = asc->script) == 0) /* sanity */ - return; - - LOG(6,"match"); - if (SCRIPT_MATCH(csr,ir,scp->condition)) { - /* - * Perform the appropriate operation, - * then proceed - */ - if ((*scp->action)(asc, csr, ir)) { - asc->script = scp + 1; - regs->asc_cmd = scp->command; mb(); - } - } else - (void) (*asc->error_handler)(asc, csr, ir); -} - -asc_target_intr(asc, csr, ir) - register asc_softc_t asc; - -{ - register script_t scp; - - LOG(0x1e,"tmode"); - - if ((asc->state & ASC_STATE_TARGET) == 0) { - - /* - * We just got selected - */ - asc->state |= ASC_STATE_TARGET; - - /* - * See if this selection collided with our selection attempt - */ - if (asc->state & ASC_STATE_BUSY) - asc->state |= ASC_STATE_COLLISION; - asc->state |= ASC_STATE_BUSY; - - return asc_selected(asc, csr, ir); - - } - /* We must be executing a script here */ - scp = asc->script; - assert(scp != 0); - - LOG(6,"match"); - if (SCRIPT_MATCH(csr,ir,scp->condition)) { - /* - * Perform the appropriate operation, - * then proceed - */ - if ((*scp->action)(asc, csr, ir)) { - asc->script = scp + 1; - asc->regs->asc_cmd = scp->command; mb(); - } - } else - (void) (*asc->error_handler)(asc, csr, ir); - -} - -/* - * All the many little things that the interrupt - * routine might switch to - */ -boolean_t -asc_clean_fifo(asc, csr, ir) - register asc_softc_t asc; - -{ - register asc_padded_regmap_t *regs = asc->regs; - register char ff; - - ASC_TC_GET(regs,asc->dmacnt_at_end); - - ASC_TC_PUT(regs,0); /* stop dma engine */ - readback(regs->asc_cmd); - - LOG(7,"clean_fifo"); - - while (fifo_count(regs)) { - ff = get_fifo(regs); - mb(); - } - return TRUE; -} - -boolean_t -asc_end(asc, csr, ir) - register asc_softc_t asc; -{ - register target_info_t *tgt; - register io_req_t ior; - - LOG(8,"end"); - - asc->state &= ~ASC_STATE_TARGET; - asc->regs->asc_syn_p = 0; mb(); - asc->regs->asc_syn_o = 0; mb(); - - tgt = asc->active_target; - if ((tgt->done = asc->done) == SCSI_RET_IN_PROGRESS) - tgt->done = SCSI_RET_SUCCESS; - - asc->script = 0; - - if (asc->wd.nactive-- == 1) - asc->wd.watchdog_state = SCSI_WD_INACTIVE; - - asc_release_bus(asc); - - if (ior = tgt->ior) { - /* - * WARNING: the above might have scheduled the - * DMA engine off to someone else. Keep it in - * mind in the following code - */ - (*asc->dma_ops->end_cmd)(asc->dma_state, tgt, ior); - - LOG(0xA,"ops->restart"); - (*tgt->dev_ops->restart)( tgt, TRUE); - } - - return FALSE; -} - -boolean_t -asc_release_bus(asc) - register asc_softc_t asc; -{ - boolean_t ret = TRUE; - - LOG(9,"release"); - if (asc->state & ASC_STATE_COLLISION) { - - LOG(0xB,"collided"); - asc->state &= ~ASC_STATE_COLLISION; - asc_attempt_selection(asc); - - } else if (queue_empty(&asc->waiting_targets)) { - - asc->state &= ~ASC_STATE_BUSY; - asc->active_target = 0; - asc->script = 0; - ret = FALSE; - - } else { - - LOG(0xC,"dequeue"); - asc->next_target = (target_info_t *) - dequeue_head(&asc->waiting_targets); - asc_attempt_selection(asc); - } - return ret; -} - -boolean_t -asc_get_status(asc, csr, ir) - register asc_softc_t asc; -{ - register asc_padded_regmap_t *regs = asc->regs; - register scsi2_status_byte_t status; - int len; - boolean_t ret; - io_req_t ior; - register target_info_t *tgt = asc->active_target; - - LOG(0xD,"get_status"); -TRWRAP - - asc->state &= ~ASC_STATE_DMA_IN; - - if (asc->state & ASC_STATE_DO_RFB) { - tgt->transient_state.has_oddb = FALSE; - regs->asc_cnfg2 = ASC_CNFG2_SCSI2; - } - - /* - * Get the last two bytes in FIFO - */ - while (fifo_count(regs) > 2) { - status.bits = get_fifo(regs); mb(); - } - - status.bits = get_fifo(regs); mb(); - - if (status.st.scsi_status_code != SCSI_ST_GOOD) { - scsi_error(asc->active_target, SCSI_ERR_STATUS, status.bits, 0); - asc->done = (status.st.scsi_status_code == SCSI_ST_BUSY) ? - SCSI_RET_RETRY : SCSI_RET_NEED_SENSE; - } else - asc->done = SCSI_RET_SUCCESS; - - status.bits = get_fifo(regs); /* just pop the command_complete */ - mb(); - - /* if reading, move the last piece of data in main memory */ - if (len = asc->in_count) { - register int count; - - count = asc->dmacnt_at_end; - if (count) { -#if 0 - this is incorrect and besides.. - tgt->ior->io_residual = count; -#endif - len -= count; - } - regs->asc_cmd = asc->script->command; - readback(regs->asc_cmd); - - ret = FALSE; - } else - ret = TRUE; - - asc->dmacnt_at_end = 0; - (*asc->dma_ops->end_xfer)(asc->dma_state, tgt, len); - if (!ret) - asc->script++; - return ret; -} - -boolean_t -asc_put_status(asc, csr, ir) - register asc_softc_t asc; -{ - register asc_padded_regmap_t *regs = asc->regs; - register scsi2_status_byte_t status; - register target_info_t *tgt = asc->active_target; - int len; - - LOG(0x21,"put_status"); - - asc->state &= ~ASC_STATE_DMA_IN; - - if (len = asc->in_count) { - register int count; - - ASC_TC_GET(regs,count); mb(); - if (count) - len -= count; - } - (*asc->dma_ops->end_xfer)(asc->dma_state, tgt, len); - -/* status.st.scsi_status_code = SCSI_ST_GOOD; */ - regs->asc_fifo = 0; mb(); - regs->asc_fifo = SCSI_COMMAND_COMPLETE; mb(); - - return TRUE; -} - - -boolean_t -asc_dma_in(asc, csr, ir) - register asc_softc_t asc; -{ - register target_info_t *tgt; - register asc_padded_regmap_t *regs = asc->regs; - register int count; - unsigned char ff = get_reg(regs,asc_flags); mb(); - - LOG(0xE,"dma_in"); - tgt = asc->active_target; - - /* - * This seems to be needed on certain rudimentary targets - * (such as the DEC TK50 tape) which apparently only pick - * up 6 initial bytes: when you add the initial IDENTIFY - * you are left with 1 pending byte, which is left in the - * FIFO and would otherwise show up atop the data we are - * really requesting. - * - * This is only speculation, though, based on the fact the - * sequence step value of 3 out of select means the target - * changed phase too quick and some bytes have not been - * xferred (see NCR manuals). Counter to this theory goes - * the fact that the extra byte that shows up is not alwyas - * zero, and appears to be pretty random. - * Note that asc_flags say there is one byte in the FIFO - * even in the ok case, but the sstep value is the right one. - * Note finally that this might all be a sync/async issue: - * I have only checked the ok case on synch disks so far. - * - * Indeed it seems to be an asynch issue: exabytes do it too. - */ - if ((tgt->sync_offset == 0) && ((ff & ASC_FLAGS_SEQ_STEP) != 0x80)) { - regs->asc_cmd = ASC_CMD_NOP; - wbflush(); - PRINT(("[tgt %d: %x while %d]", tgt->target_id, ff, tgt->cur_cmd)); - while ((ff & ASC_FLAGS_FIFO_CNT) != 0) { - ff = get_fifo(regs); mb(); - ff = get_reg(regs,asc_flags); mb(); - } - } - - asc->state |= ASC_STATE_DMA_IN; - - count = (*asc->dma_ops->start_datain)(asc->dma_state, tgt); - ASC_TC_PUT(regs, count); - readback(regs->asc_cmd); - - if ((asc->in_count = count) == tgt->transient_state.in_count) - return TRUE; - regs->asc_cmd = asc->script->command; mb(); - asc->script = asc_script_restart_data_in; - return FALSE; -} - -asc_dma_in_r(asc, csr, ir) - register asc_softc_t asc; -{ - register target_info_t *tgt; - register asc_padded_regmap_t *regs = asc->regs; - register int count; - boolean_t advance_script = TRUE; - - - LOG(0x1f,"dma_in_r"); - tgt = asc->active_target; - - asc->state |= ASC_STATE_DMA_IN; - - if (asc->in_count == 0) { - /* - * Got nothing yet, we just reconnected. - */ - register int avail; - - /* - * NOTE: if we have to handle the RFB (obb), - * the odd byte has been installed at reconnect - * time, before switching to data-in phase. Now - * we are already in data-in phase. - * It is up to the DMA engine to trim the dma_ptr - * down one byte. - */ - - count = (*asc->dma_ops->restart_datain_1) - (asc->dma_state, tgt); - - /* common case of 8k-or-less read ? */ - advance_script = (tgt->transient_state.in_count == count); - - } else { - - /* - * We received some data. - */ - register int offset, xferred; - - /* - * Problem: sometimes we get a 'spurious' interrupt - * right after a reconnect. It goes like disconnect, - * reconnect, dma_in_r, here but DMA is still rolling. - * Since there is no good reason we got here to begin with - * we just check for the case and dismiss it: we should - * get another interrupt when the TC goes to zero or the - * target disconnects. - */ - ASC_TC_GET(regs,xferred); mb(); - if (xferred != 0) - return FALSE; - - xferred = asc->in_count - xferred; - assert(xferred > 0); - - tgt->transient_state.in_count -= xferred; - assert(tgt->transient_state.in_count > 0); - - /* - * There should NOT be any obb issues here, - * we would have no control anyways. - */ - count = (*asc->dma_ops->restart_datain_2) - (asc->dma_state, tgt, xferred); - - asc->in_count = count; - ASC_TC_PUT(regs, count); - readback(regs->asc_cmd); - regs->asc_cmd = asc->script->command; mb(); - - (*asc->dma_ops->restart_datain_3) - (asc->dma_state, tgt); - - /* last chunk ? */ - if (count == tgt->transient_state.in_count) - asc->script++; - - return FALSE; - } - - asc->in_count = count; - ASC_TC_PUT(regs, count); - readback(regs->asc_cmd); - - if (!advance_script) { - regs->asc_cmd = asc->script->command; - readback(regs->asc_cmd); - } - return advance_script; -} - - -/* send data to target. Only called to start the xfer */ - -boolean_t -asc_dma_out(asc, csr, ir) - register asc_softc_t asc; -{ - register asc_padded_regmap_t *regs = asc->regs; - register int reload_count; - register target_info_t *tgt; - int command; - - LOG(0xF,"dma_out"); - - ASC_TC_GET(regs, reload_count); mb(); - asc->extra_count = fifo_count(regs); - reload_count += asc->extra_count; - ASC_TC_PUT(regs, reload_count); - asc->state &= ~ASC_STATE_DMA_IN; - readback(regs->asc_cmd); - - tgt = asc->active_target; - - command = asc->script->command; - - if (reload_count == 0) reload_count = ASC_TC_MAX; - asc->out_count = reload_count; - - if (reload_count >= tgt->transient_state.out_count) - asc->script++; - else - asc->script = asc_script_restart_data_out; - - if ((*asc->dma_ops->start_dataout) - (asc->dma_state, tgt, (volatile unsigned *)®s->asc_cmd, - command, &asc->extra_count)) { - regs->asc_cmd = command; - readback(regs->asc_cmd); - } - - return FALSE; -} - -/* send data to target. Called in two different ways: - (a) to restart a big transfer and - (b) after reconnection - */ -boolean_t -asc_dma_out_r(asc, csr, ir) - register asc_softc_t asc; -{ - register asc_padded_regmap_t *regs = asc->regs; - register target_info_t *tgt; - boolean_t advance_script = TRUE; - int count; - - - LOG(0x20,"dma_out_r"); - - tgt = asc->active_target; - asc->state &= ~ASC_STATE_DMA_IN; - - if (asc->out_count == 0) { - /* - * Nothing committed: we just got reconnected - */ - count = (*asc->dma_ops->restart_dataout_1) - (asc->dma_state, tgt); - - /* is this the last chunk ? */ - advance_script = (tgt->transient_state.out_count == count); - } else { - /* - * We sent some data. - */ - register int offset, xferred; - - ASC_TC_GET(regs,count); mb(); - - /* see comment above */ - if (count) { - return FALSE; - } - - count += fifo_count(regs); - count -= asc->extra_count; - xferred = asc->out_count - count; - assert(xferred > 0); - - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - - count = (*asc->dma_ops->restart_dataout_2) - (asc->dma_state, tgt, xferred); - - /* last chunk ? */ - if (tgt->transient_state.out_count == count) - goto quickie; - - asc->out_count = count; - - asc->extra_count = (*asc->dma_ops->restart_dataout_3) - (asc->dma_state, tgt, - (volatile unsigned *)®s->asc_fifo); - ASC_TC_PUT(regs, count); - readback(regs->asc_cmd); - regs->asc_cmd = asc->script->command; mb(); - - (*asc->dma_ops->restart_dataout_4)(asc->dma_state, tgt); - - return FALSE; - } - -quickie: - asc->extra_count = (*asc->dma_ops->restart_dataout_3) - (asc->dma_state, tgt, - (volatile unsigned *)®s->asc_fifo); - - asc->out_count = count; - - ASC_TC_PUT(regs, count); - readback(regs->asc_cmd); - - if (!advance_script) { - regs->asc_cmd = asc->script->command; - } - return advance_script; -} - -boolean_t -asc_dosynch(asc, csr, ir) - register asc_softc_t asc; - register unsigned char csr, ir; -{ - register asc_padded_regmap_t *regs = asc->regs; - register unsigned char c; - int i, per, offs; - register target_info_t *tgt; - - /* - * Phase is MSG_OUT here. - * Try to go synchronous, unless prohibited - */ - tgt = asc->active_target; - regs->asc_cmd = ASC_CMD_FLUSH; - readback(regs->asc_cmd); - delay(1); - - per = asc_min_period; - if (BGET(scsi_no_synchronous_xfer,asc->sc->masterno,tgt->target_id)) - offs = 0; - else - offs = asc_max_offset; - - tgt->flags |= TGT_DID_SYNCH; /* only one chance */ - tgt->flags &= ~TGT_TRY_SYNCH; - - regs->asc_fifo = SCSI_EXTENDED_MESSAGE; mb(); - regs->asc_fifo = 3; mb(); - regs->asc_fifo = SCSI_SYNC_XFER_REQUEST; mb(); - regs->asc_fifo = asc_to_scsi_period(asc_min_period,asc->clk); mb(); - regs->asc_fifo = offs; mb(); - regs->asc_cmd = ASC_CMD_XFER_INFO; - readback(regs->asc_cmd); - csr = asc_wait(regs, ASC_CSR_INT, 1); - ir = get_reg(regs,asc_intr); mb(); - - /* some targets might be slow to move to msg-in */ - - if (SCSI_PHASE(csr) != SCSI_PHASE_MSG_IN) { - - /* wait for direction bit to flip */ - csr = asc_wait(regs, SCSI_IO, 0); - ir = get_reg(regs,asc_intr); mb(); - /* Some ugly targets go stright to command phase. - "You could at least say goodbye" */ - if (SCSI_PHASE(csr) == SCSI_PHASE_CMD) - goto did_not; - if (SCSI_PHASE(csr) != SCSI_PHASE_MSG_IN) - gimmeabreak(); - } - - regs->asc_cmd = ASC_CMD_XFER_INFO; mb(); - csr = asc_wait(regs, ASC_CSR_INT, 1); - ir = get_reg(regs,asc_intr); mb(); - - /* some targets do not even take all the bytes out */ - while (fifo_count(regs) > 0) { - c = get_fifo(regs); /* see what it says */ - mb(); - } - - if (c == SCSI_MESSAGE_REJECT) { -did_not: - printf(" did not like SYNCH xfer "); - - /* Tk50s get in trouble with ATN, sigh. */ - regs->asc_cmd = ASC_CMD_CLR_ATN; - readback(regs->asc_cmd); - - goto cmd; - } - - /* - * Receive the rest of the message - */ - regs->asc_cmd = ASC_CMD_MSG_ACPT; mb(); - asc_wait(regs, ASC_CSR_INT, 1); - ir = get_reg(regs,asc_intr); mb(); - - if (c != SCSI_EXTENDED_MESSAGE) - gimmeabreak(); - - regs->asc_cmd = ASC_CMD_XFER_INFO; mb(); - asc_wait(regs, ASC_CSR_INT, 1); - c = get_reg(regs,asc_intr); mb(); - if (get_fifo(regs) != 3) - panic("asc_dosynch"); - - for (i = 0; i < 3; i++) { - regs->asc_cmd = ASC_CMD_MSG_ACPT; mb(); - asc_wait(regs, ASC_CSR_INT, 1); - c = get_reg(regs,asc_intr); mb(); - - regs->asc_cmd = ASC_CMD_XFER_INFO; mb(); - asc_wait(regs, ASC_CSR_INT, 1); - c = get_reg(regs,asc_intr);/*ack*/ mb(); - c = get_fifo(regs); mb(); - - if (i == 1) tgt->sync_period = scsi_period_to_asc(c,asc->clk); - if (i == 2) tgt->sync_offset = c; - } - -cmd: - regs->asc_cmd = ASC_CMD_MSG_ACPT; mb(); - csr = asc_wait(regs, ASC_CSR_INT, 1); - c = get_reg(regs,asc_intr); mb(); - - /* Might have to wait a bit longer for slow targets */ - for (c = 0; SCSI_PHASE(get_reg(regs,asc_csr)) == SCSI_PHASE_MSG_IN; c++) { - mb(); - delay(2); - if (c & 0x80) break; /* waited too long */ - } - csr = get_reg(regs,asc_csr); mb(); - - /* phase should normally be command here */ - if (SCSI_PHASE(csr) == SCSI_PHASE_CMD) { - register char *cmd = tgt->cmd_ptr; - - /* test unit ready or inquiry */ - for (i = 0; i < sizeof(scsi_command_group_0); i++) { - regs->asc_fifo = *cmd++; mb(); - } - ASC_TC_PUT(regs,0xff); mb(); - regs->asc_cmd = ASC_CMD_XFER_PAD; /*0x18*/ mb(); - - if (tgt->cur_cmd == SCSI_CMD_INQUIRY) { - tgt->transient_state.script = asc_script_data_in; - asc->script = tgt->transient_state.script; - regs->asc_syn_p = tgt->sync_period; - regs->asc_syn_o = tgt->sync_offset; mb(); - return FALSE; - } - - csr = asc_wait(regs, ASC_CSR_INT, 1); - ir = get_reg(regs,asc_intr);/*ack*/ mb(); - } - - if (SCSI_PHASE(csr) != SCSI_PHASE_STATUS) - csr = asc_wait(regs, SCSI_IO, 1); /* direction flip */ - -status: - if (SCSI_PHASE(csr) != SCSI_PHASE_STATUS) - gimmeabreak(); - - return TRUE; -} - -/* The other side of the coin.. */ -asc_odsynch(asc, initiator) - register asc_softc_t asc; - target_info_t *initiator; -{ - register asc_padded_regmap_t *regs = asc->regs; - register unsigned char c; - int len, per, offs; - - /* - * Phase is MSG_OUT, we are the target and we have control. - * Any IDENTIFY messages have been handled already. - */ - initiator->flags |= TGT_DID_SYNCH; - initiator->flags &= ~TGT_TRY_SYNCH; - - /* - * We only understand synch negotiations - */ - c = get_fifo(regs); mb(); - if (c != SCSI_EXTENDED_MESSAGE) goto bad; - - /* - * This is not in the specs, but apparently the chip knows - * enough about scsi to receive the length automatically. - * So there were two bytes in the fifo at function call. - */ - len = get_fifo(regs); mb(); - if (len != 3) goto bad; - while (len) { - if (fifo_count(regs) == 0) { - regs->asc_cmd = ASC_CMD_RCV_MSG; - readback(regs->asc_cmd); - asc_wait(regs, ASC_CSR_INT, 1); - c = get_reg(regs,asc_intr); mb(); - } - c = get_fifo(regs); mb(); - if (len == 1) offs = c; - if (len == 2) per = c; - len--; - } - - /* - * Adjust the proposed parameters - */ - c = scsi_period_to_asc(per,asc->clk); - initiator->sync_period = c; - per = asc_to_scsi_period(c,asc->clk); - - if (offs > asc_max_offset) offs = asc_max_offset; - initiator->sync_offset = offs; - - /* - * Tell him what the deal is - */ - regs->asc_fifo = SCSI_EXTENDED_MESSAGE; mb(); - regs->asc_fifo = 3; mb(); - regs->asc_fifo = SCSI_SYNC_XFER_REQUEST; mb(); - regs->asc_fifo = per; mb(); - regs->asc_fifo = offs; mb(); - regs->asc_cmd = ASC_CMD_SND_MSG; - readback(regs->asc_cmd); - asc_wait(regs, ASC_CSR_INT, 1); - c = get_reg(regs,asc_intr); mb(); - - /* - * Exit conditions: fifo empty, phase undefined but non-command - */ - return; - - /* - * Something wrong, reject the message - */ -bad: - while (fifo_count(regs)) { - c = get_fifo(regs); mb(); - } - regs->asc_fifo = SCSI_MESSAGE_REJECT; mb(); - regs->asc_cmd = ASC_CMD_SND_MSG; - readback(regs->asc_cmd); - asc_wait(regs, ASC_CSR_INT, 1); - c = get_reg(regs,asc_intr); mb(); -} - -/* - * The bus was reset - */ -asc_bus_reset(asc) - register asc_softc_t asc; -{ - register asc_padded_regmap_t *regs = asc->regs; - - LOG(0x1d,"bus_reset"); - - /* - * Clear bus descriptor - */ - asc->script = 0; - asc->error_handler = 0; - asc->active_target = 0; - asc->next_target = 0; - asc->state &= ASC_STATE_SPEC_DMA | ASC_STATE_DO_RFB; - queue_init(&asc->waiting_targets); - asc->wd.nactive = 0; - asc_reset(asc, TRUE, asc->state & ASC_STATE_SPEC_DMA); - - printf("asc: (%d) bus reset ", ++asc->wd.reset_count); - - /* some targets take long to reset */ - delay( scsi_delay_after_reset + - asc->sc->initiator_id * 500000); /* if multiple initiators */ - - if (asc->sc == 0) /* sanity */ - return; - - scsi_bus_was_reset(asc->sc); -} - -/* - * Disconnect/reconnect mode ops - */ - -/* get the message in via dma */ -boolean_t -asc_msg_in(asc, csr, ir) - register asc_softc_t asc; - register unsigned char csr, ir; -{ - register target_info_t *tgt; - register asc_padded_regmap_t *regs = asc->regs; - unsigned char ff; - - LOG(0x10,"msg_in"); - /* must clean FIFO as in asc_dma_in, sigh */ - while (fifo_count(regs) != 0) { - ff = get_fifo(regs); mb(); - } - - (void) (*asc->dma_ops->start_msgin)(asc->dma_state, asc->active_target); - /* We only really expect two bytes, at tgt->cmd_ptr */ - ASC_TC_PUT(regs, sizeof(scsi_command_group_0)); - readback(regs->asc_cmd); - - return TRUE; -} - -/* check the message is indeed a DISCONNECT */ -boolean_t -asc_disconnect(asc, csr, ir) - register asc_softc_t asc; - register unsigned char csr, ir; - -{ - register char *msgs, ff; - register target_info_t *tgt; - asc_padded_regmap_t *regs; - - tgt = asc->active_target; - - (*asc->dma_ops->end_msgin)(asc->dma_state, tgt); - - /* - * Do not do this. It is most likely a reconnection - * message that sits there already by the time we - * get here. The chip is smart enough to only dma - * the bytes that correctly came in as msg_in proper, - * the identify and selection bytes are not dma-ed. - * Yes, sometimes the hardware does the right thing. - */ -#if 0 - /* First check message got out of the fifo */ - regs = asc->regs; - while (fifo_count(regs) != 0) { - *msgs++ = get_fifo(regs); - } -#endif - msgs = tgt->cmd_ptr; - - /* A SDP message preceeds it in non-completed READs */ - if ((msgs[0] == SCSI_DISCONNECT) || /* completed */ - ((msgs[0] == SCSI_SAVE_DATA_POINTER) && /* non complete */ - (msgs[1] == SCSI_DISCONNECT))) { - /* that's the ok case */ - } else - printf("[tgt %d bad SDP: x%x]", - tgt->target_id, *((unsigned short *)msgs)); - - return TRUE; -} - -/* save all relevant data, free the BUS */ -boolean_t -asc_disconnected(asc, csr, ir) - register asc_softc_t asc; - register unsigned char csr, ir; - -{ - register target_info_t *tgt; - - LOG(0x11,"disconnected"); - asc_disconnect(asc,csr,ir); - - tgt = asc->active_target; - tgt->flags |= TGT_DISCONNECTED; - tgt->transient_state.handler = asc->error_handler; - /* anything else was saved in asc_err_disconn() */ - - PRINT(("{D%d}", tgt->target_id)); - - asc_release_bus(asc); - - return FALSE; -} - -int asc_restore_ptr = 1; - -/* get reconnect message out of fifo, restore BUS */ -boolean_t -asc_reconnect(asc, csr, ir) - register asc_softc_t asc; - register unsigned char csr, ir; - -{ - register target_info_t *tgt; - asc_padded_regmap_t *regs; - unsigned int id; - - LOG(0x12,"reconnect"); - /* - * See if this reconnection collided with a selection attempt - */ - if (asc->state & ASC_STATE_BUSY) - asc->state |= ASC_STATE_COLLISION; - - asc->state |= ASC_STATE_BUSY; - - /* find tgt: first byte in fifo is (tgt_id|our_id) */ - regs = asc->regs; - while (fifo_count(regs) > 2) /* sanity */ { - id = get_fifo(regs); mb(); - } - if (fifo_count(regs) != 2) - gimmeabreak(); - - id = get_fifo(regs); /* must decode this now */ - mb(); - id &= ~(1 << asc->sc->initiator_id); - { - register int i; - for (i = 0; id > 1; i++) - id >>= 1; - id = i; - } - - tgt = asc->sc->target[id]; - if (tgt == 0) panic("asc_reconnect"); - - /* synch things*/ - regs->asc_syn_p = tgt->sync_period; - regs->asc_syn_o = tgt->sync_offset; - readback(regs->asc_syn_o); - - /* Get IDENTIFY message */ - { - register int i = get_fifo(regs); - if ((i & SCSI_IDENTIFY) == 0) - gimmeabreak(); - i &= 0x7; - /* If not LUN 0 see which target it is */ - if (i) { - target_info_t *tgt1; - for (tgt1 = tgt->next_lun; - tgt1 && tgt1 != tgt; - tgt1 = tgt1->next_lun) - if (tgt1->lun == i) { - tgt = tgt1; - break; - } - } - } - - if (asc->state & ASC_STATE_DO_RFB) { - if (tgt->transient_state.has_oddb) { - if (tgt->sync_period) { - regs->asc_cnfg2 = ASC_CNFG2_SCSI2 | ASC_CNFG2_RFB; - wbflush(); - regs->asc_rfb = tgt->transient_state.the_oddb; - } else { - regs->asc_fifo = tgt->transient_state.the_oddb; - } - tgt->transient_state.has_oddb = FALSE; - } else { - regs->asc_cnfg2 = ASC_CNFG2_SCSI2; - } - wbflush(); - } - - PRINT(("{R%d}", id)); - if (asc->state & ASC_STATE_COLLISION) - PRINT(("[B %d-%d]", asc->active_target->target_id, id)); - - LOG(0x80+id,0); - - asc->active_target = tgt; - tgt->flags &= ~TGT_DISCONNECTED; - - asc->script = tgt->transient_state.script; - asc->error_handler = tgt->transient_state.handler; - asc->in_count = 0; - asc->out_count = 0; - - regs->asc_cmd = ASC_CMD_MSG_ACPT; - readback(regs->asc_cmd); - - /* What if there is a RESTORE_PTR msgin ? */ - if (asc_restore_ptr) { -more_msgin: - csr = asc_wait(regs, ASC_CSR_INT, 1); - - if (SCSI_PHASE(csr) == SCSI_PHASE_MSG_IN) { - /* ack intr */ - id = get_reg(regs,asc_intr); mb(); - - /* Ok, get msg */ - regs->asc_cmd = ASC_CMD_XFER_INFO; - readback(regs->asc_cmd); - /* wait for xfer done */ - csr = asc_wait(regs, ASC_CSR_INT, 1); - - /* look at what we got */ - id = get_fifo(regs); - - if (id != SCSI_RESTORE_POINTERS) - printf("asc%d: uhu msg %x\n", asc->sc->masterno, id); - /* ack intr */ - id = get_reg(regs,asc_intr); mb(); - - /* move on */ - regs->asc_cmd = ASC_CMD_MSG_ACPT; - readback(regs->asc_cmd); - goto more_msgin; - } - } - - return FALSE; -} - - -/* We have been selected as target */ - -boolean_t -asc_selected(asc, csr, ir) - register asc_softc_t asc; - register unsigned csr, ir; -{ - register asc_padded_regmap_t *regs = asc->regs; - register unsigned char id; - target_info_t *self, *initiator; - unsigned int len; - - /* - * Find initiator's id: the head of the fifo is (init_id|our_id) - */ - - id = get_fifo(regs); /* must decode this now */ - mb(); - id &= ~(1 << asc->sc->initiator_id); - { - register int i; - for (i = 0; id > 1; i++) - id >>= 1; - id = i; - } - - /* - * See if we have seen him before - */ - self = asc->sc->target[asc->sc->initiator_id]; - initiator = asc->sc->target[id]; - if (initiator == 0) { - - initiator = scsi_slave_alloc(asc->sc->masterno, id, asc); - (*asc->dma_ops->new_target)(asc->dma_state, initiator); - - } - - if (! (initiator->flags & TGT_ONLINE) ) - sccpu_new_initiator(self, initiator); - - /* - * If selected with ATN the chip did the msg-out - * phase already, let us look at the message(s) - */ - if (ir & ASC_INT_SEL_ATN) { - register unsigned char m; - - m = get_fifo(regs); mb(); - if ((m & SCSI_IDENTIFY) == 0) - gimmeabreak(); - - csr = get_reg(regs,asc_csr); mb(); - if ((SCSI_PHASE(csr) == SCSI_PHASE_MSG_OUT) && - fifo_count(regs)) - asc_odsynch(asc, initiator); - - /* Get the command now, unless we have it already */ - mb(); - if (fifo_count(regs) < sizeof(scsi_command_group_0)) { - regs->asc_cmd = ASC_CMD_RCV_CMD; - readback(regs->asc_cmd); - asc_wait(regs, ASC_CSR_INT, 1); - ir = get_reg(regs,asc_intr); mb(); - csr = get_reg(regs,asc_csr); mb(); - } - } else { - /* - * Pop away the null byte that follows the id - */ - if (get_fifo(regs) != 0) - gimmeabreak(); - - } - - /* - * Take rest of command out of fifo - */ - self->dev_info.cpu.req_pending = TRUE; - self->dev_info.cpu.req_id = id; - self->dev_info.cpu.req_cmd = get_fifo(regs); - self->dev_info.cpu.req_lun = get_fifo(regs); - - LOG(0x80+self->dev_info.cpu.req_cmd, 0); - - switch ((self->dev_info.cpu.req_cmd & SCSI_CODE_GROUP) >> 5) { - case 0: - len = get_fifo(regs) << 16; mb(); - len |= get_fifo(regs) << 8; mb(); - len |= get_fifo(regs); mb(); - break; - case 1: - case 2: - len = get_fifo(regs); /* xxx lba1 */ mb(); - len = get_fifo(regs); /* xxx lba2 */ mb(); - len = get_fifo(regs); /* xxx lba3 */ mb(); - len = get_fifo(regs); /* xxx lba4 */ mb(); - len = get_fifo(regs); /* xxx xxx */ mb(); - len = get_fifo(regs) << 8; mb(); - len |= get_fifo(regs); mb(); - break; - case 5: - len = get_fifo(regs); /* xxx lba1 */ mb(); - len = get_fifo(regs); /* xxx lba2 */ mb(); - len = get_fifo(regs); /* xxx lba3 */ mb(); - len = get_fifo(regs); /* xxx lba4 */ mb(); - len = get_fifo(regs) << 24; mb(); - len |= get_fifo(regs) << 16; mb(); - len |= get_fifo(regs) << 8; mb(); - len |= get_fifo(regs); mb(); - if (get_fifo(regs) != 0) ; - break; - default: - panic("asc_selected"); - } - self->dev_info.cpu.req_len = len; -/*if (scsi_debug) printf("[L x%x]", len);*/ - - /* xxx pop the cntrl byte away */ - if (get_fifo(regs) != 0) - gimmeabreak(); - mb(); - - /* - * Setup state - */ - asc->active_target = self; - asc->done = SCSI_RET_IN_PROGRESS; - asc->out_count = 0; - asc->in_count = 0; - asc->extra_count = 0; - - /* - * Sync params. - */ - regs->asc_syn_p = initiator->sync_period; - regs->asc_syn_o = initiator->sync_offset; - readback(regs->asc_syn_o); - - /* - * Do the up-call - */ - LOG(0xB,"tgt-mode-restart"); - (*self->dev_ops->restart)( self, FALSE); - - /* The call above has either prepared the data, - placing an ior on self, or it handled it some - other way */ - if (self->ior == 0) - return FALSE; - - /* sanity */ - if (fifo_count(regs)) { - regs->asc_cmd = ASC_CMD_FLUSH; - readback(regs->asc_cmd); - } - - /* needed by some dma code to align things properly */ - self->transient_state.cmd_count = sizeof(scsi_command_group_0); - self->transient_state.in_count = len; /* XXX */ - - (*asc->dma_ops->map)(asc->dma_state, self); - - if (asc->wd.nactive++ == 0) - asc->wd.watchdog_state = SCSI_WD_ACTIVE; - - - { - register script_t scp; - unsigned char command; - - switch (self->dev_info.cpu.req_cmd) { - case SCSI_CMD_TEST_UNIT_READY: - scp = asc_script_t_data_in+1; break; - case SCSI_CMD_SEND: - scp = asc_script_t_data_in; break; - default: - scp = asc_script_t_data_out; break; - } - - asc->script = scp; - command = scp->command; - if (!(*scp->action)(asc, csr, ir)) - return FALSE; - -/*if (scsi_debug) printf("[F%x]", fifo_count(regs));*/ - - asc->script++; - regs->asc_cmd = command; mb(); - - } - - return FALSE; -} - - -/* - * Other utilities - */ -private void -pick_up_oddb( - target_info_t *tgt) -{ - register char *lastp; - - /* State should have been updated before we get here */ - lastp = tgt->dma_ptr + tgt->transient_state.dma_offset; - - if ((vm_offset_t) lastp & 1) { - tgt->transient_state.has_oddb = TRUE; - tgt->transient_state.the_oddb = lastp[-1]; - } else - tgt->transient_state.has_oddb = FALSE; -} - - -/* - * Error handlers - */ - -/* - * Fall-back error handler. - */ -asc_err_generic(asc, csr, ir) - register asc_softc_t asc; -{ - LOG(0x13,"err_generic"); - - /* handle non-existant or powered off devices here */ - if ((ir == ASC_INT_DISC) && - (asc_isa_select(asc->cmd_was)) && - (ASC_SS(asc->ss_was) == 0)) { - /* Powered off ? */ - target_info_t *tgt = asc->active_target; - - tgt->flags = 0; - tgt->sync_period = 0; - tgt->sync_offset = 0; mb(); - asc->done = SCSI_RET_DEVICE_DOWN; - asc_end(asc, csr, ir); - return; - } - - switch (SCSI_PHASE(csr)) { - case SCSI_PHASE_STATUS: - if (asc->script[-1].condition == SCSI_PHASE_STATUS) { - /* some are just slow to get out.. */ - } else - asc_err_to_status(asc, csr, ir); - return; - break; - case SCSI_PHASE_DATAI: - if (asc->script->condition == SCSI_PHASE_STATUS) { - /* - * Here is what I know about it. We reconnect to - * the target (csr 87, ir 0C, cmd 44), start dma in - * (81 10 12) and then get here with (81 10 90). - * Dma is rolling and keeps on rolling happily, - * the value in the counter indicates the interrupt - * was signalled right away: by the time we get - * here only 80-90 bytes have been shipped to an - * rz56 running synchronous at 3.57 Mb/sec. - */ -/* printf("{P}");*/ - return; - } - break; - case SCSI_PHASE_DATAO: - if (asc->script->condition == SCSI_PHASE_STATUS) { - /* - * See comment above. Actually seen on hitachis. - */ -/* printf("{P}");*/ - return; - } - break; - case SCSI_PHASE_CMD: - /* This can be the case with drives that are not - even scsi-1 compliant and do not like to be - selected with ATN (to do the synch negot) and - go stright to command phase, regardless */ - - if (asc->script == asc_script_try_synch) { - - target_info_t *tgt = asc->active_target; - register asc_padded_regmap_t *regs = asc->regs; - - tgt->flags |= TGT_DID_SYNCH; /* only one chance */ - tgt->flags &= ~TGT_TRY_SYNCH; - - if (tgt->cur_cmd == SCSI_CMD_INQUIRY) - tgt->transient_state.script = asc_script_data_in; - else - tgt->transient_state.script = asc_script_simple_cmd; - asc->script = tgt->transient_state.script; - regs->asc_cmd = ASC_CMD_CLR_ATN; - readback(regs->asc_cmd); - asc->regs->asc_cmd = ASC_CMD_XFER_PAD|ASC_CMD_DMA; /*0x98*/ mb(); - printf(" did not like SYNCH xfer "); - return; - } - /* fall through */ - } - gimmeabreak(); -} - -/* - * Handle generic errors that are reported as - * an unexpected change to STATUS phase - */ -asc_err_to_status(asc, csr, ir) - register asc_softc_t asc; -{ - script_t scp = asc->script; - - LOG(0x14,"err_tostatus"); - while (scp->condition != SCSI_PHASE_STATUS) - scp++; - (*scp->action)(asc, csr, ir); - asc->script = scp + 1; - asc->regs->asc_cmd = scp->command; mb(); -#if 0 - /* - * Normally, we would already be able to say the command - * is in error, e.g. the tape had a filemark or something. - * But in case we do disconnected mode WRITEs, it is quite - * common that the following happens: - * dma_out -> disconnect (xfer complete) -> reconnect - * and our script might expect at this point that the dma - * had to be restarted (it didn't notice it was completed). - * And in any event.. it is both correct and cleaner to - * declare error iff the STATUS byte says so. - */ - asc->done = SCSI_RET_NEED_SENSE; -#endif -} - -/* - * Handle disconnections as exceptions - */ -asc_err_disconn(asc, csr, ir) - register asc_softc_t asc; - register unsigned char csr, ir; -{ - register asc_padded_regmap_t *regs; - register target_info_t *tgt; - int count; - boolean_t callback = FALSE; - - LOG(0x16,"err_disconn"); - - /* - * We only do msg-in cases here - */ - if (SCSI_PHASE(csr) != SCSI_PHASE_MSG_IN) - return asc_err_generic(asc, csr, ir); - - regs = asc->regs; - tgt = asc->active_target; - - /* - * What did we expect to happen, and what did happen. - */ - switch (asc->script->condition) { - case SCSI_PHASE_DATAO: - /* - * A data out phase was either about to be started, - * or it was in progress but more had to go out later - * [e.g. a big xfer for instance, or more than the - * DMA engine can take in one shot]. - */ - LOG(0x1b,"+DATAO"); - if (asc->out_count) { - register int xferred, offset; - - /* - * Xfer in progress. See where we stopped. - */ - ASC_TC_GET(regs,xferred); /* temporary misnomer */ - /* - * Account for prefetching, in its various forms - */ - xferred += fifo_count(regs); - xferred -= asc->extra_count; - /* - * See how much went out, how much to go. - */ - xferred = asc->out_count - xferred; /* ok now */ - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - - callback = (*asc->dma_ops->disconn_1) - (asc->dma_state, tgt, xferred); - - } else { - - /* - * A disconnection before DMA was (re)started. - */ - callback = (*asc->dma_ops->disconn_2) - (asc->dma_state, tgt); - - } - asc->extra_count = 0; - tgt->transient_state.script = asc_script_restart_data_out; - break; - - - case SCSI_PHASE_DATAI: - /* - * Same as above, the other way around - */ - LOG(0x17,"+DATAI"); - if (asc->in_count) { - register int offset, xferred; - - /* - * How much did we expect, how much did we get - */ - ASC_TC_GET(regs,count); mb(); - xferred = asc->in_count - count; - assert(xferred > 0); - -if (regs->asc_flags & 0xf) -printf("{Xf %x,%x,%x}", xferred, asc->in_count, fifo_count(regs)); - tgt->transient_state.in_count -= xferred; - assert(tgt->transient_state.in_count > 0); - - callback = (*asc->dma_ops->disconn_3) - (asc->dma_state, tgt, xferred); - - /* - * Handle obb if we have to. DMA code has - * updated pointers and flushed buffers. - */ - if (asc->state & ASC_STATE_DO_RFB) - pick_up_oddb(tgt); - - tgt->transient_state.script = asc_script_restart_data_in; - /* - * Some silly targets disconnect after they - * have given us all the data. - */ - if (tgt->transient_state.in_count == 0) - tgt->transient_state.script++; - - } else - tgt->transient_state.script = asc_script_restart_data_in; - break; - - case SCSI_PHASE_STATUS: - /* - * Either one of the above cases here. Only diff - * the DMA engine was setup to run to completion - * and (most likely) did not. - */ - ASC_TC_GET(regs,count); mb(); - if (asc->state & ASC_STATE_DMA_IN) { - register int offset, xferred; - - LOG(0x1a,"+STATUS+R"); - - - /* - * Handle brain-dead sequence: - * 1-xfer all data, disconnect - * 2-reconnect, disconnect immediately ?? - * 3-rept 2 - * 4-reconnect,complete - */ - if (asc->in_count) { - - xferred = asc->in_count - count; - assert(xferred > 0); -if (regs->asc_flags & 0xf) -printf("{Xf %x,%x,%x}", xferred, asc->in_count, fifo_count(regs)); - - tgt->transient_state.in_count -= xferred; - - callback = (*asc->dma_ops->disconn_4) - (asc->dma_state, tgt, xferred); - } - /* - * Handle obb if we have to. DMA code has - * updated pointers and flushed buffers. - */ - if (asc->state & ASC_STATE_DO_RFB) - pick_up_oddb(tgt); - - tgt->transient_state.script = asc_script_restart_data_in; - - /* see previous note */ - if (tgt->transient_state.in_count == 0) - tgt->transient_state.script++; - - } else { - - /* - * Outgoing xfer, take care of prefetching. - */ - /* add what's left in the fifo */ - count += fifo_count(regs); - /* take back the extra we might have added */ - count -= asc->extra_count; - /* ..and drop that idea */ - asc->extra_count = 0; - - LOG(0x19,"+STATUS+W"); - - /* - * All done ? This is less silly than with - * READs: some disks will only say "done" when - * the data is down on the platter, and some - * people like it much better that way. - */ - if ((count == 0) && (tgt->transient_state.out_count == asc->out_count)) { - /* all done */ - tgt->transient_state.script = asc->script; - tgt->transient_state.out_count = 0; - } else { - register int xferred, offset; - - /* how much we xferred */ - xferred = asc->out_count - count; - - /* how much to go */ - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - - callback = (*asc->dma_ops->disconn_5) - (asc->dma_state,tgt,xferred); - - tgt->transient_state.script = asc_script_restart_data_out; - } - asc->out_count = 0; - } - break; - default: - gimmeabreak(); - return; - } - asc_msg_in(asc,csr,ir); - asc->script = asc_script_disconnect; - regs->asc_cmd = ASC_CMD_XFER_INFO|ASC_CMD_DMA; - wbflush(); - /* - * Prevent a race, now. If the reselection comes quickly - * the chip will prefetch and reload the transfer counter - * register. Make sure it will stop, by reloading a zero. - */ - regs->asc_tc_lsb = 0; - regs->asc_tc_msb = 0; - if (callback) - (*asc->dma_ops->disconn_callback)(asc->dma_state, tgt); -} - -/* - * Watchdog - * - * So far I have only seen the chip get stuck in a - * select/reselect conflict: the reselection did - * win and the interrupt register showed it but.. - * no interrupt was generated. - * But we know that some (name withdrawn) disks get - * stuck in the middle of dma phases... - */ -asc_reset_scsibus(asc) - register asc_softc_t asc; -{ - register target_info_t *tgt = asc->active_target; - register asc_padded_regmap_t *regs = asc->regs; - register int ir; - - if (scsi_debug && tgt) { - int dmalen; - ASC_TC_GET(asc->regs,dmalen); mb(); - printf("Target %d was active, cmd x%x in x%x out x%x Sin x%x Sou x%x dmalen x%x\n", - tgt->target_id, tgt->cur_cmd, - tgt->transient_state.in_count, tgt->transient_state.out_count, - asc->in_count, asc->out_count, - dmalen); - } - ir = get_reg(regs,asc_intr); mb(); - if ((ir & ASC_INT_RESEL) && (SCSI_PHASE(regs->asc_csr) == SCSI_PHASE_MSG_IN)) { - /* getting it out of the woods is a bit tricky */ - spl_t s = splbio(); - - (void) asc_reconnect(asc, get_reg(regs,asc_csr), ir); - asc_wait(regs, ASC_CSR_INT, 1); - ir = get_reg(regs,asc_intr); mb(); - regs->asc_cmd = ASC_CMD_MSG_ACPT; - readback(regs->asc_cmd); - splx(s); - } else { - regs->asc_cmd = ASC_CMD_BUS_RESET; mb(); - delay(35); - } -} - -#endif NASC > 0 - diff --git a/scsi/adapters/scsi_7061.h b/scsi/adapters/scsi_7061.h deleted file mode 100644 index 8969f8b..0000000 --- a/scsi/adapters/scsi_7061.h +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_7061.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 9/90 - * - * Defines for the DEC DC7061 SII gate array (SCSI interface) - */ - -/* - * Register map - */ - -typedef struct { - volatile unsigned short sii_sdb; /* rw: Data bus and parity */ - volatile unsigned short sii_sc1; /* rw: scsi signals 1 */ - volatile unsigned short sii_sc2; /* rw: scsi signals 2 */ - volatile unsigned short sii_csr; /* rw: control and status */ - volatile unsigned short sii_id; /* rw: scsi bus ID */ - volatile unsigned short sii_sel_csr; /* rw: selection status */ - volatile unsigned short sii_destat; /* ro: selection detector status */ - volatile unsigned short sii_dstmo; /* unsupp: dssi timeout */ - volatile unsigned short sii_data; /* rw: data register */ - volatile unsigned short sii_dma_ctrl; /* rw: dma control reg */ - volatile unsigned short sii_dma_len; /* rw: length of transfer */ - volatile unsigned short sii_dma_adr_low;/* rw: low address */ - volatile unsigned short sii_dma_adr_hi; /* rw: high address */ - volatile unsigned short sii_dma_1st_byte;/* rw: initial byte */ - volatile unsigned short sii_stlp; /* unsupp: dssi short trgt list ptr */ - volatile unsigned short sii_ltlp; /* unsupp: dssi long " " " */ - volatile unsigned short sii_ilp; /* unsupp: dssi initiator list ptr */ - volatile unsigned short sii_dssi_csr; /* unsupp: dssi control */ - volatile unsigned short sii_conn_csr; /* rc: connection interrupt control */ - volatile unsigned short sii_data_csr; /* rc: data interrupt control */ - volatile unsigned short sii_cmd; /* rw: command register */ - volatile unsigned short sii_diag_csr; /* rw: disgnostic status */ -} sii_regmap_t; - -/* - * Data bus register (diag) - */ - -#define SII_SDB_DATA 0x00ff /* data bits, assert high */ -#define SII_SDB_PARITY 0x0100 /* parity bit */ - -/* - * Control signals one (diag) - */ - -#define SII_CS1_IO 0x0001 /* I/O bit */ -#define SII_CS1_CD 0x0002 /* Control/Data bit */ -#define SII_CS1_MSG 0x0004 /* Message bit */ -#define SII_CS1_ATN 0x0008 /* Attention bit */ -#define SII_CS1_REQ 0x0010 /* Request bit */ -#define SII_CS1_ACK 0x0020 /* Acknowledge bit */ -#define SII_CS1_RST 0x0040 /* Reset bit */ -#define SII_CS1_SEL 0x0080 /* Selection bit */ -#define SII_CS1_BSY 0x0100 /* Busy bit */ - -/* - * Control signals two (diag) - */ - -#define SII_CS2_SBE 0x0001 /* Bus enable */ -#define SII_CS2_ARB 0x0002 /* arbitration enable */ -#define SII_CS2_TGS 0x0004 /* Target role steer */ -#define SII_CS2_IGS 0x0008 /* Initiator role steer */ - -/* - * Control and status register - */ - -#define SII_CSR_IE 0x0001 /* Interrupt enable */ -#define SII_CSR_PCE 0x0002 /* Parity check enable */ -#define SII_CSR_SLE 0x0004 /* Select enable */ -#define SII_CSR_RSE 0x0008 /* Reselect enable */ -#define SII_CSR_HPM 0x0010 /* Arbitration enable */ - -/* - * SCSI bus ID register - */ - -#define SII_ID_MASK 0x0007 /* The scsi ID */ -#define SII_ID_IO 0x8000 /* ID pins are in/out */ - -/* - * Selector control and status register - */ - -#define SII_SEL_ID 0x0003 /* Destination ID */ - -/* - * Selection detector status register - */ - -#define SII_DET_ID 0x0003 /* Selector's ID */ - -/* - * Data register (silo) - */ - -#define SII_DATA_VAL 0x00ff /* Lower byte */ - -/* - * DMA control register - */ - -#define SII_DMA_SYN_OFFSET 0x0003 /* 0 -> asynch */ - -/* - * DMA counter - */ - -#define SII_DMA_COUNT_MASK 0x1fff /* in bytes */ - -/* - * DMA address registers - */ - -#define SII_DMA_LOW_MASK 0xffff /* all bits */ -#define SII_DMA_HIGH_MASK 0x0003 /* unused ones mbz */ - -/* - * DMA initial byte - */ - -#define SII_DMA_IBYTE 0x00ff /* for odd address DMAs */ - -/* - * Connection status register - */ - -#define SII_CON_LST 0x0002 /* ro: lost arbitration */ -#define SII_CON_SIP 0x0004 /* ro: selection InProgress */ -#define SII_CON_SWA 0x0008 /* rc: selected with ATN */ -#define SII_CON_TGT 0x0010 /* ro: target role */ -#define SII_CON_DST 0x0020 /* ro: sii is destination */ -#define SII_CON_CON 0x0040 /* ro: sii is connected */ -#define SII_CON_SCH 0x0080 /* rci: state change */ -#define SII_CON_LDN 0x0100 /* ??i: dssi list elm done */ -#define SII_CON_BUF 0x0200 /* ??i: dssi buffer service */ -#define SII_CON_TZ 0x0400 /* ??: dssi target zero */ -#define SII_CON_OBC 0x0800 /* ??i: dssi outen bit clr */ -#define SII_CON_BERR 0x1000 /* rci: bus error */ -#define SII_CON_RST 0x2000 /* rci: RST asserted */ -#define SII_CON_DI 0x4000 /* ro: data_csr intr */ -#define SII_CON_CI 0x8000 /* ro: con_csr intr */ - -/* - * Data transfer status register - */ - -#define SII_DTR_IO 0x0001 /* ro: I/O asserted */ -#define SII_DTR_CD 0x0002 /* ro: CD asserted */ -#define SII_DTR_MSG 0x0004 /* ro: MSG asserted */ -#define SII_DTR_ATN 0x0008 /* rc: ATN found asserted */ -#define SII_DTR_MIS 0x0010 /* roi: phase mismatch */ -#define SII_DTR_OBB 0x0100 /* ro: odd byte boundry */ -#define SII_DTR_IPE 0x0200 /* ro: incoming parity err */ -#define SII_DTR_IBF 0x0400 /* roi: input buffer full */ -#define SII_DTR_TBE 0x0800 /* roi: xmt buffer empty */ -#define SII_DTR_TCZ 0x1000 /* ro: xfer counter zero */ -#define SII_DTR_DONE 0x2000 /* rci: xfer complete */ -#define SII_DTR_DI 0x4000 /* ro: data_csr intr */ -#define SII_DTR_CI 0x8000 /* ro: con_csr intr */ - -#define SII_PHASE(dtr) SCSI_PHASE(dtr) - - -/* - * Command register - * - * Certain bits are only valid in certain roles: - * I - Initiator D - Destination T - Target - * Bits 0-3 give the 'expected phase' - * Bits 4-6 give the 'expected state' - * Bits 7-11 are the 'command' proper - */ - -#define SII_CMD_IO 0x0001 /* rw: (T) assert I/O */ -#define SII_CMD_CD 0x0002 /* rw: (T) assert CD */ -#define SII_CMD_MSG 0x0004 /* rw: (T) assert MSG */ -#define SII_CMD_ATN 0x0008 /* rw: (I) assert ATN */ - -#define SII_CMD_TGT 0x0010 /* rw: (DIT) target */ -#define SII_CMD_DST 0x0020 /* rw: (DIT) destination */ -#define SII_CMD_CON 0x0040 /* rw: (DIT) connected */ - -#define SII_CMD_RESET 0x0080 /* rw: (DIT) reset */ -#define SII_CMD_DIS 0x0100 /* rw: (DIT) disconnect */ -#define SII_CMD_REQ 0x0200 /* rw: (T) request data */ -#define SII_CMD_SEL 0x0400 /* rw: (D) select */ -#define SII_CMD_XFER 0x0800 /* rw: (IT) xfer information */ - -#define SII_CMD_RSL 0x1000 /* rw: reselect target */ -#define SII_CMD_RST 0x4000 /* zw: assert RST */ -#define SII_CMD_DMA 0x8000 /* rw: command uses DMA */ - -/* - * Diagnostic control register - */ - -#define SII_DIAG_TEST 0x0001 /* rw: test mode */ -#define SII_DIAG_DIA 0x0002 /* rw: ext loopback mode */ -#define SII_DIAG_PORT_ENB 0x0004 /* rw: enable drivers */ -#define SII_DIAG_LPB 0x0008 /* rw: loopback reg writes */ diff --git a/scsi/adapters/scsi_7061_hdw.c b/scsi/adapters/scsi_7061_hdw.c deleted file mode 100644 index 674e892..0000000 --- a/scsi/adapters/scsi_7061_hdw.c +++ /dev/null @@ -1,2603 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_7061_hdw.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Bottom layer of the SCSI driver: chip-dependent functions - * - * This file contains the code that is specific to the DEC DC7061 - * SCSI chip (Host Bus Adapter in SCSI parlance): probing, start - * operation, and interrupt routine. - */ - -/* - * This layer works based on small simple 'scripts' that are installed - * at the start of the command and drive the chip to completion. - * The idea comes from the specs of the NCR 53C700 'script' processor. - * - * There are various reasons for this, mainly - * - Performance: identify the common (successful) path, and follow it; - * at interrupt time no code is needed to find the current status - * - Code size: it should be easy to compact common operations - * - Adaptability: the code skeleton should adapt to different chips without - * terrible complications. - * - Error handling: and it is easy to modify the actions performed - * by the scripts to cope with strange but well identified sequences - * - */ - -#include <sii.h> -#if NSII > 0 - -#include <platforms.h> - -#ifdef DECSTATION -#define PAD(n) short n -#endif - -#include <machine/machspl.h> /* spl definitions */ -#include <mach/std_types.h> -#include <chips/busses.h> -#include <scsi/compat_30.h> -#include <machine/machspl.h> - -#include <sys/syslog.h> - -#include <scsi/scsi.h> -#include <scsi/scsi2.h> -#include <scsi/scsi_defs.h> - -#define isa_oddbb hba_dep[0] -#define oddbb hba_dep[1] - -#include <scsi/adapters/scsi_7061.h> - -#ifdef PAD - -typedef struct { - volatile unsigned short sii_sdb; /* rw: Data bus and parity */ - PAD(pad0); - volatile unsigned short sii_sc1; /* rw: scsi signals 1 */ - PAD(pad1); - volatile unsigned short sii_sc2; /* rw: scsi signals 2 */ - PAD(pad2); - volatile unsigned short sii_csr; /* rw: control and status */ - PAD(pad3); - volatile unsigned short sii_id; /* rw: scsi bus ID */ - PAD(pad4); - volatile unsigned short sii_sel_csr; /* rw: selection status */ - PAD(pad5); - volatile unsigned short sii_destat; /* ro: selection detector status */ - PAD(pad6); - volatile unsigned short sii_dstmo; /* unsupp: dssi timeout */ - PAD(pad7); - volatile unsigned short sii_data; /* rw: data register */ - PAD(pad8); - volatile unsigned short sii_dma_ctrl; /* rw: dma control reg */ - PAD(pad9); - volatile unsigned short sii_dma_len; /* rw: length of transfer */ - PAD(pad10); - volatile unsigned short sii_dma_adr_low;/* rw: low address */ - PAD(pad11); - volatile unsigned short sii_dma_adr_hi; /* rw: high address */ - PAD(pad12); - volatile unsigned short sii_dma_1st_byte;/* rw: initial byte */ - PAD(pad13); - volatile unsigned short sii_stlp; /* unsupp: dssi short trgt list ptr */ - PAD(pad14); - volatile unsigned short sii_ltlp; /* unsupp: dssi long " " " */ - PAD(pad15); - volatile unsigned short sii_ilp; /* unsupp: dssi initiator list ptr */ - PAD(pad16); - volatile unsigned short sii_dssi_csr; /* unsupp: dssi control */ - PAD(pad17); - volatile unsigned short sii_conn_csr; /* rc: connection interrupt control */ - PAD(pad18); - volatile unsigned short sii_data_csr; /* rc: data interrupt control */ - PAD(pad19); - volatile unsigned short sii_cmd; /* rw: command register */ - PAD(pad20); - volatile unsigned short sii_diag_csr; /* rw: disgnostic status */ - PAD(pad21); -} sii_padded_regmap_t; - -#else /*!PAD*/ - -typedef sii_regmap_t sii_padded_regmap_t; - -#endif /*!PAD*/ - - -#undef SII_CSR_SLE -#define SII_CSR_SLE 0 /* for now */ - -#ifdef DECSTATION -#include <mips/PMAX/kn01.h> -#define SII_OFFSET_RAM (KN01_SYS_SII_B_START-KN01_SYS_SII) -#define SII_RAM_SIZE (KN01_SYS_SII_B_END-KN01_SYS_SII_B_START) -/* 16 bits in 32 bit envelopes */ -#define SII_DMADR_LO(ptr) ((((unsigned)ptr)>>1)&SII_DMA_LOW_MASK) -#define SII_DMADR_HI(ptr) ((((unsigned)ptr)>>(16+1))&SII_DMA_HIGH_MASK) -#endif /* DECSTATION */ - -#ifndef SII_OFFSET_RAM /* cross compile check */ -#define SII_OFFSET_RAM 0 -#define SII_RAM_SIZE 0x10000 -#define SII_DMADR_LO(ptr) (((unsigned)ptr)>>16) -#define SII_DMADR_HI(ptr) (((unsigned)ptr)&0xffff) -#endif - -/* - * Statically partition the DMA buffer between targets. - * This way we will eventually be able to attach/detach - * drives on-fly. And 18k/target is enough. - */ -#define PER_TGT_DMA_SIZE ((SII_RAM_SIZE/7) & ~(sizeof(int)-1)) - -/* - * Round to 4k to make debug easier - */ -#define PER_TGT_BUFF_SIZE ((PER_TGT_DMA_SIZE >> 12) << 12) - -/* - * Macros to make certain things a little more readable - */ -#define SII_COMMAND(regs,cs,ds,cmd) \ - { \ - (regs)->sii_cmd = ((cs) & 0x70) | \ - ((ds) & 0x07) | (cmd); \ - wbflush(); \ - } -#define SII_ACK(regs,cs,ds,cmd) \ - { \ - SII_COMMAND(regs,cs,ds,cmd); \ - (regs)->sii_conn_csr = (cs); \ - (regs)->sii_data_csr = (ds); \ - } - -/* - * Deal with bogus pmax dma buffer - */ - -static char decent_buffer[NSII*8][256]; - -/* - * A script has a three parts: a pre-condition, an action, and - * an optional command to the chip. The first triggers error - * handling if not satisfied and in our case it is formed by the - * values of the sii_conn_csr and sii_data_csr register - * bits. The action part is just a function pointer, and the - * command is what the 7061 should be told to do at the end - * of the action processing. This command is only issued and the - * script proceeds if the action routine returns TRUE. - * See sii_intr() for how and where this is all done. - */ - -typedef struct script { - int condition; /* expected state at interrupt */ - int (*action)(); /* extra operations */ - int command; /* command to the chip */ -} *script_t; - -#define SCRIPT_MATCH(cs,ds) ((cs)&0x70|SCSI_PHASE((ds))) - -#define SII_PHASE_DISC 0x4 /* sort of .. */ - -/* When no command is needed */ -#define SCRIPT_END -1 - -/* forward decls of script actions */ -boolean_t - sii_script_true(), /* when nothing needed */ - sii_identify(), /* send identify msg */ - sii_dosynch(), /* negotiate synch xfer */ - sii_dma_in(), /* get data from target via dma */ - sii_dma_out(), /* send data to target via dma */ - sii_get_status(), /* get status from target */ - sii_end_transaction(), /* all come to an end */ - sii_msg_in(), /* get disconnect message(s) */ - sii_disconnected(); /* current target disconnected */ -/* forward decls of error handlers */ -boolean_t - sii_err_generic(), /* generic error handler */ - sii_err_disconn(), /* when a target disconnects */ - sii_err_rdp(), /* in reconn, handle rdp mgs */ - gimmeabreak(); /* drop into the debugger */ - -int sii_reset_scsibus(); -boolean_t sii_probe_target(); -static sii_wait(); - -/* - * State descriptor for this layer. There is one such structure - * per (enabled) SCSI-7061 interface - */ -struct sii_softc { - watchdog_t wd; - sii_padded_regmap_t *regs; - volatile char *buff; - script_t script; - int (*error_handler)(); - int in_count; /* amnt we expect to receive */ - int out_count; /* amnt we are going to ship */ - - volatile char state; -#define SII_STATE_BUSY 0x01 /* selecting or currently connected */ -#define SII_STATE_TARGET 0x04 /* currently selected as target */ -#define SII_STATE_COLLISION 0x08 /* lost selection attempt */ -#define SII_STATE_DMA_IN 0x10 /* tgt --> initiator xfer */ - - unsigned char ntargets; /* how many alive on this scsibus */ - unsigned char done; - unsigned char cmd_count; - - scsi_softc_t *sc; - target_info_t *active_target; - - target_info_t *next_target; /* trying to seize bus */ - queue_head_t waiting_targets;/* other targets competing for bus */ - -} sii_softc_data[NSII]; - -typedef struct sii_softc *sii_softc_t; - -sii_softc_t sii_softc[NSII]; - -/* - * Synch xfer parameters, and timing conversions - */ -int sii_min_period = 63; /* in 4 ns units */ -int sii_max_offset = 3; /* pure number */ - -#define sii_to_scsi_period(a) (a) -#define scsi_period_to_sii(p) (((p) < sii_min_period) ? sii_min_period : (p)) - -/* - * Definition of the controller for the auto-configuration program. - */ - -int sii_probe(), scsi_slave(), sii_go(), sii_intr(); -extern void scsi_attach(); - -vm_offset_t sii_std[NSII] = { 0 }; -struct bus_device *sii_dinfo[NSII*8]; -struct bus_ctlr *sii_minfo[NSII]; -struct bus_driver sii_driver = - { sii_probe, scsi_slave, scsi_attach, sii_go, sii_std, "rz", sii_dinfo, - "sii", sii_minfo, /*BUS_INTR_B4_PROBE?*/}; - -/* - * Scripts - */ -struct script -sii_script_data_in[] = { - { SCSI_PHASE_CMD|SII_CON_CON, sii_script_true, - (SII_CMD_XFER|SII_CMD_DMA)|SII_CON_CON|SCSI_PHASE_CMD}, - { SCSI_PHASE_DATAI|SII_CON_CON, sii_dma_in, - (SII_CMD_XFER|SII_CMD_DMA)|SII_CON_CON|SCSI_PHASE_DATAI}, - { SCSI_PHASE_STATUS|SII_CON_CON, sii_get_status, - SII_CMD_XFER|SII_CON_CON|SCSI_PHASE_STATUS}, - { SCSI_PHASE_MSG_IN|SII_CON_CON, sii_end_transaction, SCRIPT_END} -}, - -sii_script_data_out[] = { - { SCSI_PHASE_CMD|SII_CON_CON, sii_script_true, - (SII_CMD_XFER|SII_CMD_DMA)|SII_CON_CON|SCSI_PHASE_CMD}, - { SCSI_PHASE_DATAO|SII_CON_CON, sii_dma_out, - (SII_CMD_XFER|SII_CMD_DMA)|SII_CON_CON|SCSI_PHASE_DATAO}, - { SCSI_PHASE_STATUS|SII_CON_CON, sii_get_status, - SII_CMD_XFER|SII_CON_CON|SCSI_PHASE_STATUS}, - { SCSI_PHASE_MSG_IN|SII_CON_CON, sii_end_transaction, SCRIPT_END} -}, - -sii_script_cmd[] = { - { SCSI_PHASE_CMD|SII_CON_CON, sii_script_true, - (SII_CMD_XFER|SII_CMD_DMA)|SII_CON_CON|SCSI_PHASE_CMD}, - { SCSI_PHASE_STATUS|SII_CON_CON, sii_get_status, - SII_CMD_XFER|SII_CON_CON|SCSI_PHASE_STATUS}, - { SCSI_PHASE_MSG_IN|SII_CON_CON, sii_end_transaction, SCRIPT_END} -}, - -/* Same, after a disconnect */ - -sii_script_restart_data_in[] = { - { SCSI_PHASE_DATAI|SII_CON_CON|SII_CON_DST, sii_dma_in, - (SII_CMD_XFER|SII_CMD_DMA)|SII_CON_CON|SII_CON_DST|SCSI_PHASE_DATAI}, - { SCSI_PHASE_STATUS|SII_CON_CON|SII_CON_DST, sii_get_status, - SII_CMD_XFER|SII_CON_CON|SII_CON_DST|SCSI_PHASE_STATUS}, - { SCSI_PHASE_MSG_IN|SII_CON_CON|SII_CON_DST, sii_end_transaction, SCRIPT_END} -}, - -sii_script_restart_data_out[] = { - { SCSI_PHASE_DATAO|SII_CON_CON|SII_CON_DST, sii_dma_out, - (SII_CMD_XFER|SII_CMD_DMA)|SII_CON_CON|SII_CON_DST|SCSI_PHASE_DATAO}, - { SCSI_PHASE_STATUS|SII_CON_CON|SII_CON_DST, sii_get_status, - SII_CMD_XFER|SII_CON_CON|SII_CON_DST|SCSI_PHASE_STATUS}, - { SCSI_PHASE_MSG_IN|SII_CON_CON|SII_CON_DST, sii_end_transaction, SCRIPT_END} -}, - -sii_script_restart_cmd[] = { - { SCSI_PHASE_STATUS|SII_CON_CON|SII_CON_DST, sii_get_status, - SII_CMD_XFER|SII_CON_CON|SII_CON_DST|SCSI_PHASE_STATUS}, - { SCSI_PHASE_MSG_IN|SII_CON_CON|SII_CON_DST, sii_end_transaction, SCRIPT_END} -}, - -/* Synchronous transfer negotiation */ - -sii_script_try_synch[] = { - { SCSI_PHASE_MSG_OUT|SII_CON_CON, sii_dosynch, SCRIPT_END} -}, - -/* Disconnect sequence */ - -sii_script_disconnect[] = { - { SII_PHASE_DISC, sii_disconnected, SCRIPT_END} -}; - - - -#define u_min(a,b) (((a) < (b)) ? (a) : (b)) - - -#define DEBUG -#ifdef DEBUG - -sii_state(regs) - sii_padded_regmap_t *regs; -{ - unsigned dmadr; - - if (regs == 0) - regs = (sii_padded_regmap_t*) 0xba000000; - - dmadr = regs->sii_dma_adr_low | (regs->sii_dma_adr_hi << 16); - db_printf("sc %x, dma %x @ x%X, cs %x, ds %x, cmd %x\n", - (unsigned) regs->sii_sc1, - (unsigned) regs->sii_dma_len, dmadr, - (unsigned) regs->sii_conn_csr, - (unsigned) regs->sii_data_csr, - (unsigned) regs->sii_cmd); - -} -sii_target_state(tgt) - target_info_t *tgt; -{ - if (tgt == 0) - tgt = sii_softc[0]->active_target; - if (tgt == 0) - return 0; - db_printf("@x%x: fl %X dma %X+%X cmd %x@%X id %X per %X off %X ior %X ret %X\n", - tgt, - tgt->flags, tgt->dma_ptr, tgt->transient_state.dma_offset, tgt->cur_cmd, - tgt->cmd_ptr, tgt->target_id, tgt->sync_period, tgt->sync_offset, - tgt->ior, tgt->done); - if (tgt->flags & TGT_DISCONNECTED){ - script_t spt; - - spt = tgt->transient_state.script; - db_printf("disconnected at "); - db_printsym(spt,1); - db_printf(": %X %X ", spt->condition, spt->command); - db_printsym(spt->action,1); - db_printf(", "); - db_printsym(tgt->transient_state.handler, 1); - db_printf("\n"); - } - - return 0; -} - -sii_all_targets(unit) -{ - int i; - target_info_t *tgt; - for (i = 0; i < 8; i++) { - tgt = sii_softc[unit]->sc->target[i]; - if (tgt) - sii_target_state(tgt); - } -} - -sii_script_state(unit) -{ - script_t spt = sii_softc[unit]->script; - - if (spt == 0) return 0; - db_printsym(spt,1); - db_printf(": %X %X ", spt->condition, spt->command); - db_printsym(spt->action,1); - db_printf(", "); - db_printsym(sii_softc[unit]->error_handler, 1); - return 0; - -} - -#define PRINT(x) if (scsi_debug) printf x - -#define TRMAX 200 -int tr[TRMAX+3]; -int trpt, trpthi; -#define TR(x) tr[trpt++] = x -#define TRWRAP trpthi = trpt; trpt = 0; -#define TRCHECK if (trpt > TRMAX) {TRWRAP} - -#define TRACE - -#ifdef TRACE - -#define LOGSIZE 256 -int sii_logpt; -char sii_log[LOGSIZE]; - -#define MAXLOG_VALUE 0x25 -struct { - char *name; - unsigned int count; -} logtbl[MAXLOG_VALUE]; - -static LOG(e,f) - char *f; -{ - sii_log[sii_logpt++] = (e); - if (sii_logpt == LOGSIZE) sii_logpt = 0; - if ((e) < MAXLOG_VALUE) { - logtbl[(e)].name = (f); - logtbl[(e)].count++; - } -} - -sii_print_log(skip) - int skip; -{ - register int i, j; - register unsigned char c; - - for (i = 0, j = sii_logpt; i < LOGSIZE; i++) { - c = sii_log[j]; - if (++j == LOGSIZE) j = 0; - if (skip-- > 0) - continue; - if (c < MAXLOG_VALUE) - db_printf(" %s", logtbl[c].name); - else - db_printf("-x%x", c & 0x7f); - } - db_printf("\n"); - return 0; -} - -sii_print_stat() -{ - register int i; - register char *p; - for (i = 0; i < MAXLOG_VALUE; i++) { - if (p = logtbl[i].name) - printf("%d %s\n", logtbl[i].count, p); - } -} - -#else /* TRACE */ -#define LOG(e,f) -#endif /* TRACE */ - -struct cnt { - unsigned int zeroes; - unsigned int usage; - unsigned int avg; - unsigned int min; - unsigned int max; -}; - -static bump(counter, value) - register struct cnt *counter; - register unsigned int value; -{ - register unsigned int n; - - if (value == 0) { - counter->zeroes++; - return; - } - n = counter->usage + 1; - counter->usage = n; - if (n == 0) { - printf("{Counter at x%x overflowed with avg x%x}", - counter, counter->avg); - return; - } else - if (n == 1) - counter->min = 0xffffffff; - - counter->avg = ((counter->avg * (n - 1)) + value) / n; - if (counter->min > value) - counter->min = value; - if (counter->max < value) - counter->max = value; -} - -struct cnt - s_cnt; - -#else /* DEBUG */ -#define PRINT(x) -#define LOG(e,f) -#define TR(x) -#define TRCHECK -#define TRWRAP -#endif /* DEBUG */ - - -/* - * Probe/Slave/Attach functions - */ - -/* - * Probe routine: - * Should find out (a) if the controller is - * present and (b) which/where slaves are present. - * - * Implementation: - * Send an identify msg to each possible target on the bus - * except of course ourselves. - */ -sii_probe(reg, ui) - unsigned reg; - struct bus_ctlr *ui; -{ - int unit = ui->unit; - sii_softc_t sii = &sii_softc_data[unit]; - int target_id, i; - scsi_softc_t *sc; - register sii_padded_regmap_t *regs; - spl_t s; - boolean_t did_banner = FALSE; - char *dma_ptr; - static char *here = "sii_probe"; - - /* - * We are only called if the chip is there, - * but make sure anyways.. - */ - if (check_memory(reg, 0)) - return 0; - -#ifdef MACH_KERNEL - /* Mappable version side */ - SII_probe(reg, ui); -#endif /*MACH_KERNEL*/ - - /* - * Initialize hw descriptor - */ - sii_softc[unit] = sii; - sii->regs = (sii_padded_regmap_t *) (reg); - sii->buff = (volatile char*) (reg + SII_OFFSET_RAM); - - queue_init(&sii->waiting_targets); - - sc = scsi_master_alloc(unit, sii); - sii->sc = sc; - - sc->go = sii_go; - sc->watchdog = scsi_watchdog; - sc->probe = sii_probe_target; - - sii->wd.reset = sii_reset_scsibus; - -#ifdef MACH_KERNEL - sc->max_dma_data = -1; /* unlimited */ -#else - sc->max_dma_data = scsi_per_target_virtual; -#endif - - regs = sii->regs; - - /* - * Clear out dma buffer - */ - blkclr(sii->buff, SII_RAM_SIZE); - - /* - * Reset chip, fully. - */ - s = splbio(); - sii_reset(regs, TRUE); - - /* - * Our SCSI id on the bus. - * The user can set this via the prom on pmaxen/3maxen. - * If this changes it is easy to fix: make a default that - * can be changed as boot arg. - */ -#ifdef unneeded - regs->sii_id = (scsi_initiator_id[unit] & SII_ID_MASK)|SII_ID_IO; -#endif - sc->initiator_id = regs->sii_id & SII_ID_MASK; - printf("%s%d: my SCSI id is %d", ui->name, unit, sc->initiator_id); - - /* - * For all possible targets, see if there is one and allocate - * a descriptor for it if it is there. - */ - for (target_id = 0, dma_ptr = (char*)sii->buff; - target_id < 8; - target_id++, dma_ptr += (PER_TGT_DMA_SIZE*2)) { - - register unsigned csr, dsr; - register scsi_status_byte_t status; - - /* except of course ourselves */ - if (target_id == sc->initiator_id) - continue; - - regs->sii_sel_csr = target_id; - wbflush(); - - /* select */ - regs->sii_cmd = SII_CMD_SEL; - wbflush(); - - /* wait for a selection timeout delay, and some more */ - delay(251000); - - dsr = regs->sii_data_csr; - csr = regs->sii_conn_csr; - if ((csr & SII_CON_CON) == 0) { - - regs->sii_conn_csr = csr;/*wtc bits*/ - - /* abort sel in progress */ - if (csr & SII_CON_SIP) { - regs->sii_cmd = SII_CMD_DIS; - wbflush(); - csr = sii_wait(®s->sii_conn_csr, SII_CON_SCH,1); - regs->sii_conn_csr = 0xffff;/*wtc bits */ - regs->sii_data_csr = 0xffff; - regs->sii_cmd = 0; - wbflush(); - } - continue; - } - - printf(",%s%d", did_banner++ ? " " : " target(s) at ", - target_id); - - /* should be command phase here */ - if (SCSI_PHASE(dsr) != SCSI_PHASE_CMD) - panic(here); - - /* acknowledge state change */ - SII_ACK(regs,csr,dsr,0); - - /* build command in (bogus) dma area */ - { - unsigned int *p = (unsigned int*) dma_ptr; - - p[0] = SCSI_CMD_TEST_UNIT_READY | (0 << 8); - p[1] = 0 | (0 << 8); - p[2] = 0 | (0 << 8); - } - - /* set up dma xfer parameters */ - regs->sii_dma_len = 6; - regs->sii_dma_adr_low = SII_DMADR_LO(dma_ptr); - regs->sii_dma_adr_hi = SII_DMADR_HI(dma_ptr); - wbflush(); - - /* issue dma command */ - SII_COMMAND(regs,csr,dsr,SII_CMD_XFER|SII_CMD_DMA); - - /* wait till done */ - dsr = sii_wait(®s->sii_data_csr, SII_DTR_DONE,1); - regs->sii_cmd &= ~(SII_CMD_XFER|SII_CMD_DMA); - regs->sii_data_csr = SII_DTR_DONE;/* clear */ - regs->sii_dma_len = 0; - - /* move on to status phase */ - dsr = sii_wait(®s->sii_data_csr, SCSI_PHASE_STATUS,1); - csr = regs->sii_conn_csr; - SII_ACK(regs,csr,dsr,0); - - if (SCSI_PHASE(dsr) != SCSI_PHASE_STATUS) - panic(here); - - /* get status byte */ - dsr = sii_wait(®s->sii_data_csr, SII_DTR_IBF,1); - csr = regs->sii_conn_csr; - - status.bits = regs->sii_data; - if (status.st.scsi_status_code != SCSI_ST_GOOD) - scsi_error( 0, SCSI_ERR_STATUS, status.bits, 0); - - /* get cmd_complete message */ - SII_ACK(regs,csr,dsr,0); - SII_COMMAND(regs,csr,dsr,SII_CMD_XFER); - dsr = sii_wait(®s->sii_data_csr, SII_DTR_DONE,1); - - dsr = sii_wait(®s->sii_data_csr, SCSI_PHASE_MSG_IN,1); - csr = regs->sii_conn_csr; - - - SII_ACK(regs,csr,dsr,0); - i = regs->sii_data; - SII_COMMAND(regs,csr,dsr,SII_CMD_XFER); - - /* check disconnected, clear all intr bits */ - csr = sii_wait(®s->sii_conn_csr, SII_CON_SCH,1); - if (regs->sii_conn_csr & SII_CON_CON) - panic(here); - - regs->sii_data_csr = 0xffff; - regs->sii_conn_csr = 0xffff; - regs->sii_cmd = 0; - - /* - * Found a target - */ - sii->ntargets++; - { - register target_info_t *tgt; - tgt = scsi_slave_alloc(sc->masterno, target_id, sii); - - tgt->dma_ptr = dma_ptr; - tgt->cmd_ptr = decent_buffer[unit*8 + target_id]; -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - fdma_init(&tgt->fdma, scsi_per_target_virtual); -#endif /*MACH_KERNEL*/ - } - } - printf(".\n"); - - splx(s); - return 1; -} - -boolean_t -sii_probe_target(tgt, ior) - target_info_t *tgt; - io_req_t ior; -{ - sii_softc_t sii = sii_softc[tgt->masterno]; - boolean_t newlywed; - int sii_probe_timeout(); - - newlywed = (tgt->cmd_ptr == 0); - if (newlywed) { - /* desc was allocated afresh */ - char *dma_ptr = (char*)sii->buff; - - dma_ptr += (PER_TGT_DMA_SIZE * tgt->target_id)*2; - tgt->dma_ptr = dma_ptr; - tgt->cmd_ptr = decent_buffer[tgt->masterno*8 + tgt->target_id]; -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - fdma_init(&tgt->fdma, scsi_per_target_virtual); -#endif /*MACH_KERNEL*/ - - } - - /* Unfortunately, the SII chip does not have timeout support - for selection */ - timeout(sii_probe_timeout, tgt, hz); - - if (scsi_inquiry(tgt, SCSI_INQ_STD_DATA) == SCSI_RET_DEVICE_DOWN) - return FALSE; - - untimeout(sii_probe_timeout, tgt); - tgt->flags = TGT_ALIVE; - return TRUE; -} - -sii_probe_timeout(tgt) - target_info_t *tgt; -{ - sii_softc_t sii = (sii_softc_t)tgt->hw_state; - register sii_padded_regmap_t *regs = sii->regs; - int cs, ds; - spl_t s; - - /* cancelled ? */ - if (tgt->done != SCSI_RET_IN_PROGRESS) - return; - - s = splbio(); - - /* Someone else might be using the bus (rare) */ - switch (regs->sii_conn_csr & (SII_CON_LST|SII_CON_SIP)) { - case SII_CON_SIP: - /* We really timed out */ - break; - case SII_CON_SIP|SII_CON_LST: - /* Someone else is (still) using the bus */ - sii->wd.watchdog_state = SCSI_WD_ACTIVE; - /* fall-through */ - default: - /* Did not get a chance to the bus yet */ - timeout(sii_probe_timeout, tgt, hz); - goto ret; - } - regs->sii_cmd = SII_CMD_DIS; - wbflush(); - regs->sii_csr |= SII_CSR_RSE; - regs->sii_cmd = 0; - wbflush(); - - sii->done = SCSI_RET_DEVICE_DOWN; - cs = regs->sii_conn_csr; - ds = regs->sii_data_csr; - if (!sii_end(sii, cs, ds)) - (void) sii_reconnect(sii, cs, ds); -ret: - splx(s); -} - - -static sii_wait(preg, until, complain) - volatile unsigned short *preg; -{ - int timeo = 1000000; - while ((*preg & until) != until) { - delay(1); - if (!timeo--) { - if (complain) { - gimmeabreak(); - printf("sii_wait TIMEO with x%x\n", *preg); - } - break; - } - } -#ifdef DEBUG - bump(&s_cnt, 1000000-timeo); -#endif - return *preg; -} - -sii_reset(regs, quickly) - register sii_padded_regmap_t *regs; - boolean_t quickly; -{ - int my_id; - - my_id = regs->sii_id & SII_ID_MASK; - - regs->sii_cmd = SII_CMD_RESET; - wbflush(); - delay(30); - - /* clear them all random bitsy */ - regs->sii_conn_csr = SII_CON_SWA|SII_CON_SCH|SII_CON_BERR|SII_CON_RST; - regs->sii_data_csr = SII_DTR_ATN|SII_DTR_DONE; - - regs->sii_id = my_id | SII_ID_IO; - - regs->sii_dma_ctrl = 0; /* asynch */ - - regs->sii_dma_len = 0; - regs->sii_dma_adr_low = 0; - regs->sii_dma_adr_hi = 0; - - regs->sii_csr = SII_CSR_IE|SII_CSR_PCE|SII_CSR_SLE|SII_CSR_HPM; - /* later: SII_CSR_RSE */ - - regs->sii_diag_csr = SII_DIAG_PORT_ENB; - wbflush(); - - if (quickly) - return; - - /* - * reset the scsi bus, the interrupt routine does the rest - * or you can call sii_bus_reset(). - */ - regs->sii_cmd = SII_CMD_RST; - -} - -/* - * Operational functions - */ - -/* - * Start a SCSI command on a target - */ -sii_go(tgt, cmd_count, in_count, cmd_only) - target_info_t *tgt; - boolean_t cmd_only; -{ - sii_softc_t sii; - register spl_t s; - boolean_t disconn; - script_t scp; - boolean_t (*handler)(); - - LOG(1,"go"); - - sii = (sii_softc_t)tgt->hw_state; - - /* - * We cannot do real DMA. - */ -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - if (tgt->ior) - fdma_map(&tgt->fdma, tgt->ior); -#endif /*MACH_KERNEL*/ - - copyout_gap16(tgt->cmd_ptr, tgt->dma_ptr, cmd_count); - - if ((tgt->cur_cmd == SCSI_CMD_WRITE) || - (tgt->cur_cmd == SCSI_CMD_LONG_WRITE)){ - io_req_t ior = tgt->ior; - register int len = ior->io_count; - - tgt->transient_state.out_count = len; - - if (len > PER_TGT_BUFF_SIZE) - len = PER_TGT_BUFF_SIZE; - copyout_gap16( ior->io_data, - tgt->dma_ptr + (cmd_count<<1), - len); - tgt->transient_state.copy_count = len; - - /* avoid leaks */ - if (len < tgt->block_size) { - bzero_gap16(tgt->dma_ptr + ((cmd_count + len)<<1), - len - tgt->block_size); - len = tgt->block_size; - tgt->transient_state.copy_count = len; - } - - } else { - tgt->transient_state.out_count = 0; - tgt->transient_state.copy_count = 0; - } - - tgt->transient_state.cmd_count = cmd_count; - tgt->transient_state.isa_oddbb = FALSE; - - disconn = BGET(scsi_might_disconnect,tgt->masterno,tgt->target_id); - disconn = disconn && (sii->ntargets > 1); - disconn |= BGET(scsi_should_disconnect,tgt->masterno,tgt->target_id); - - /* - * Setup target state - */ - tgt->done = SCSI_RET_IN_PROGRESS; - - handler = (disconn) ? sii_err_disconn : sii_err_generic; - - switch (tgt->cur_cmd) { - case SCSI_CMD_READ: - case SCSI_CMD_LONG_READ: - LOG(0x13,"readop"); - scp = sii_script_data_in; - break; - case SCSI_CMD_WRITE: - case SCSI_CMD_LONG_WRITE: - LOG(0x14,"writeop"); - scp = sii_script_data_out; - break; - case SCSI_CMD_INQUIRY: - /* This is likely the first thing out: - do the synch neg if so */ - if (!cmd_only && ((tgt->flags&TGT_DID_SYNCH)==0)) { - scp = sii_script_try_synch; - tgt->flags |= TGT_TRY_SYNCH; - break; - } - case SCSI_CMD_REQUEST_SENSE: - case SCSI_CMD_MODE_SENSE: - case SCSI_CMD_RECEIVE_DIAG_RESULTS: - case SCSI_CMD_READ_CAPACITY: - case SCSI_CMD_READ_BLOCK_LIMITS: - case SCSI_CMD_READ_TOC: - case SCSI_CMD_READ_SUBCH: - case SCSI_CMD_READ_HEADER: - case 0xc4: /* despised: SCSI_CMD_DEC_PLAYBACK_STATUS */ - case 0xdd: /* despised: SCSI_CMD_NEC_READ_SUBCH_Q */ - case 0xde: /* despised: SCSI_CMD_NEC_READ_TOC */ - scp = sii_script_data_in; - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - case SCSI_CMD_MODE_SELECT: - case SCSI_CMD_REASSIGN_BLOCKS: - case SCSI_CMD_FORMAT_UNIT: - case 0xc9: /* vendor-spec: SCSI_CMD_DEC_PLAYBACK_CONTROL */ - tgt->transient_state.cmd_count = sizeof_scsi_command(tgt->cur_cmd); - tgt->transient_state.out_count = - cmd_count - tgt->transient_state.cmd_count; - scp = sii_script_data_out; - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - case SCSI_CMD_TEST_UNIT_READY: - /* - * Do the synch negotiation here, unless done already - */ - if (tgt->flags & TGT_DID_SYNCH) { - scp = sii_script_cmd; - } else { - scp = sii_script_try_synch; - tgt->flags |= TGT_TRY_SYNCH; - } - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - default: - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - scp = sii_script_cmd; - } - - tgt->transient_state.script = scp; - tgt->transient_state.handler = handler; - tgt->transient_state.identify = (cmd_only) ? 0xff : - (disconn ? SCSI_IDENTIFY|SCSI_IFY_ENABLE_DISCONNECT : - SCSI_IDENTIFY); - - if (in_count) - tgt->transient_state.in_count = - (in_count < tgt->block_size) ? tgt->block_size : in_count; - else - tgt->transient_state.in_count = 0; - - tgt->transient_state.dma_offset = 0; - - /* - * See if another target is currently selected on - * this SCSI bus, e.g. lock the sii structure. - * Note that it is the strategy routine's job - * to serialize ops on the same target as appropriate. - * XXX here and everywhere, locks! - */ - /* - * Protection viz reconnections makes it tricky. - */ -/* s = splbio();*/ - s = splhigh(); - - if (sii->wd.nactive++ == 0) - sii->wd.watchdog_state = SCSI_WD_ACTIVE; - - if (sii->state & SII_STATE_BUSY) { - /* - * Queue up this target, note that this takes care - * of proper FIFO scheduling of the scsi-bus. - */ - LOG(3,"enqueue"); - LOG(0x80+tgt->target_id,0); - enqueue_tail(&sii->waiting_targets, (queue_entry_t) tgt); - } else { - /* - * It is down to at most two contenders now, - * we will treat reconnections same as selections - * and let the scsi-bus arbitration process decide. - */ - sii->state |= SII_STATE_BUSY; - sii->next_target = tgt; - sii_attempt_selection(sii); - /* - * Note that we might still lose arbitration.. - */ - } - splx(s); -} - -sii_attempt_selection(sii) - sii_softc_t sii; -{ - target_info_t *tgt; - register int out_count; - sii_padded_regmap_t *regs; - register int cmd; - - regs = sii->regs; - tgt = sii->next_target; - - LOG(4,"select"); - LOG(0x80+tgt->target_id,0); - - /* - * Init bus state variables and set registers. - * [They are intermixed to avoid wbflush()es] - */ - sii->active_target = tgt; - - out_count = tgt->transient_state.cmd_count; - - /* set dma pointer and counter */ - regs->sii_dma_len = out_count; - regs->sii_dma_adr_low = SII_DMADR_LO(tgt->dma_ptr); - regs->sii_dma_adr_hi = SII_DMADR_HI(tgt->dma_ptr); - - sii->error_handler = tgt->transient_state.handler; - - regs->sii_sel_csr = tgt->target_id; - - sii->done = SCSI_RET_IN_PROGRESS; - - regs->sii_dma_ctrl = tgt->sync_offset; - - sii->cmd_count = out_count; - -/* if (regs->sii_conn_csr & (SII_CON_CON|SII_CON_DST))*/ - if (regs->sii_sc1 & (SII_CS1_BSY|SII_CS1_SEL)) - return; - regs->sii_csr = SII_CSR_IE|SII_CSR_PCE|SII_CSR_SLE|SII_CSR_HPM; - - sii->script = tgt->transient_state.script; - sii->in_count = 0; - sii->out_count = 0; - - if (tgt->flags & TGT_DID_SYNCH) { - if (tgt->transient_state.identify == 0xff) - cmd = SII_CMD_SEL; - else { - cmd = SII_CMD_SEL | SII_CMD_ATN | - SII_CMD_CON | SII_CMD_XFER | SCSI_PHASE_MSG_OUT; - /* chain select and message out */ -/*??*/ regs->sii_dma_1st_byte = tgt->transient_state.identify; - } - } else if (tgt->flags & TGT_TRY_SYNCH) - cmd = SII_CMD_SEL | SII_CMD_ATN; - else - cmd = SII_CMD_SEL; - -/* if (regs->sii_conn_csr & (SII_CON_CON|SII_CON_DST)) { */ - if (regs->sii_sc1 & (SII_CS1_BSY|SII_CS1_SEL)) { - /* let the reconnection attempt proceed */ - regs->sii_csr = SII_CSR_IE|SII_CSR_PCE|SII_CSR_SLE| - SII_CSR_HPM|SII_CSR_RSE; - sii->script = 0; - LOG(0x8c,0); - } else { - regs->sii_cmd = cmd; - wbflush(); - } -} - -/* - * Interrupt routine - * Take interrupts from the chip - * - * Implementation: - * Move along the current command's script if - * all is well, invoke error handler if not. - */ -boolean_t sii_inside_sii_intr = FALSE; - -sii_intr(unit,spllevel) -{ - register sii_softc_t sii; - register script_t scp; - register int cs, ds; - register sii_padded_regmap_t *regs; - boolean_t try_match; -#ifdef MACH_KERNEL - extern boolean_t rz_use_mapped_interface; - - if (rz_use_mapped_interface) - return SII_intr(unit,spllevel); -#endif /*MACH_KERNEL*/ - - /* interrupt code is NOT reentrant */ - if (sii_inside_sii_intr) { - LOG(0x22,"!!attempted to reenter sii_intr!!"); - return; - } - sii_inside_sii_intr = TRUE; - - LOG(5,"\n\tintr"); - - sii = sii_softc[unit]; - - /* collect status information */ - regs = sii->regs; - cs = regs->sii_conn_csr; - ds = regs->sii_data_csr; - -TR(cs); -TR(ds); -TR(regs->sii_cmd); -TRCHECK; - - if (cs & SII_CON_RST){ - sii_bus_reset(sii); - goto getout; - } - - /* we got an interrupt allright */ - if (sii->active_target) - sii->wd.watchdog_state = SCSI_WD_ACTIVE; - - /* rid of DONEs */ - if (ds & SII_DTR_DONE) { - regs->sii_data_csr = SII_DTR_DONE; - LOG(0x1e,"done"); - ds = regs->sii_data_csr; - cs = regs->sii_conn_csr; - } - - /* drop spurious calls, note that sometimes - * ds and cs get out-of-sync */ - if (((cs & SII_CON_CI) | (ds & SII_DTR_DI)) == 0) { - LOG(2,"SPURIOUS"); - goto getout; - } - - /* clear interrupt flags */ - - regs->sii_conn_csr = cs; - regs->sii_data_csr = cs; - - /* drop priority */ - splx(spllevel); - - if ((sii->state & SII_STATE_TARGET) || - (cs & SII_CON_TGT)) { - sii_target_intr(sii,cs,ds); - goto getout; - } - - scp = sii->script; - - /* check who got the bus */ - if ((scp == 0) || (cs & SII_CON_LST)) { - if (cs & SII_CON_DST) { - sii_reconnect(sii, cs, ds); - goto getout; - } - LOG(0x12,"no-script"); - goto getout; - } - - if (SCRIPT_MATCH(cs,ds) != scp->condition) { - if (try_match = (*sii->error_handler)(sii, cs, ds)) { - cs = regs->sii_conn_csr; - ds = regs->sii_data_csr; - } - } else - try_match = TRUE; - - /* might have been side effected */ - scp = sii->script; - - if (try_match && (SCRIPT_MATCH(cs,ds) == scp->condition)) { - /* - * Perform the appropriate operation, - * then proceed - */ - if ((*scp->action)(sii, cs, ds)) { - /* might have been side effected */ - scp = sii->script; - sii->script = scp + 1; - regs->sii_cmd = scp->command; - wbflush(); - } - } -getout: - sii_inside_sii_intr = FALSE; -} - - -sii_target_intr(sii) - register sii_softc_t sii; -{ - panic("SII: TARGET MODE !!!\n"); -} - -/* - * All the many little things that the interrupt - * routine might switch to - */ -boolean_t -sii_script_true(sii, cs, ds) - register sii_softc_t sii; - -{ - SII_COMMAND(sii->regs,cs,ds,SII_CON_CON/*sanity*/); - LOG(7,"nop"); - return TRUE; -} - -boolean_t -sii_end_transaction( sii, cs, ds) - register sii_softc_t sii; -{ - register sii_padded_regmap_t *regs = sii->regs; - - SII_COMMAND(sii->regs,cs,ds,0); - - LOG(0x1f,"end_t"); - - regs->sii_csr &= ~SII_CSR_RSE; - - /* is the fifo really clean here ? */ - ds = sii_wait(®s->sii_data_csr, SII_DTR_IBF,1); - - if (regs->sii_data != SCSI_COMMAND_COMPLETE) - printf("{T%x}", regs->sii_data); - - regs->sii_cmd = SII_CMD_XFER | SII_CON_CON | SCSI_PHASE_MSG_IN | - (cs & SII_CON_DST); - wbflush(); - - ds = sii_wait(®s->sii_data_csr, SII_DTR_DONE,1); - regs->sii_data_csr = SII_DTR_DONE; - - regs->sii_cmd = 0/*SII_PHASE_DISC*/; - wbflush(); - - cs = regs->sii_conn_csr; - - if ((cs & SII_CON_SCH) == 0) - cs = sii_wait(®s->sii_conn_csr, SII_CON_SCH,1); - regs->sii_conn_csr = SII_CON_SCH; - - regs->sii_csr |= SII_CSR_RSE; - - cs = regs->sii_conn_csr; - - if (!sii_end(sii, cs, ds)) - (void) sii_reconnect(sii, cs, ds); - return FALSE; -} - -boolean_t -sii_end( sii, cs, ds) - register sii_softc_t sii; -{ - register target_info_t *tgt; - register io_req_t ior; - register sii_padded_regmap_t *regs = sii->regs; - - LOG(6,"end"); - - tgt = sii->active_target; - - if ((tgt->done = sii->done) == SCSI_RET_IN_PROGRESS) - tgt->done = SCSI_RET_SUCCESS; - - sii->script = 0; - - if (sii->wd.nactive-- == 1) - sii->wd.watchdog_state = SCSI_WD_INACTIVE; - - /* check reconnection not pending */ - cs = regs->sii_conn_csr; - if ((cs & SII_CON_DST) == 0) - sii_release_bus(sii); - else { - sii->active_target = 0; -/* sii->state &= ~SII_STATE_BUSY; later */ - } - - if (ior = tgt->ior) { - LOG(0xA,"ops->restart"); -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - fdma_unmap(&tgt->fdma, ior); -#endif /*MACH_KERNEL*/ - (*tgt->dev_ops->restart)(tgt, TRUE); - if (cs & SII_CON_DST) - sii->state &= ~SII_STATE_BUSY; - } - - return ((cs & SII_CON_DST) == 0); -} - -boolean_t -sii_release_bus(sii) - register sii_softc_t sii; -{ - boolean_t ret = FALSE; - - LOG(9,"release"); - - sii->script = 0; - - if (sii->state & SII_STATE_COLLISION) { - - LOG(0xB,"collided"); - sii->state &= ~SII_STATE_COLLISION; - sii_attempt_selection(sii); - - } else if (queue_empty(&sii->waiting_targets)) { - - sii->state &= ~SII_STATE_BUSY; - sii->active_target = 0; - ret = TRUE; - - } else { - - LOG(0xC,"dequeue"); - sii->next_target = (target_info_t *) - dequeue_head(&sii->waiting_targets); - sii_attempt_selection(sii); - } - return ret; -} - -boolean_t -sii_get_status( sii, cs, ds) - register sii_softc_t sii; -{ - register sii_padded_regmap_t *regs = sii->regs; - register scsi2_status_byte_t status; - register target_info_t *tgt; - unsigned int len; - unsigned short cmd; - - LOG(0xD,"get_status"); -TRWRAP; - - sii->state &= ~SII_STATE_DMA_IN; - - tgt = sii->active_target; - sii->error_handler = tgt->transient_state.handler; - - if (len = sii->in_count) { - if ((tgt->cur_cmd != SCSI_CMD_READ) && - (tgt->cur_cmd != SCSI_CMD_LONG_READ)){ - len -= regs->sii_dma_len; - copyin_gap16(tgt->dma_ptr, tgt->cmd_ptr, len); - if (len & 0x1) /* odd byte, left in silo */ - tgt->cmd_ptr[len - 1] = regs->sii_data; - } else { - if (regs->sii_dma_len) { -#if 0 - this is incorrect and besides.. - tgt->ior->io_residual = regs->sii_dma_len; -#endif - len -= regs->sii_dma_len; - } - careful_copyin_gap16( tgt, tgt->transient_state.dma_offset, - len, ds & SII_DTR_OBB, - regs->sii_dma_1st_byte); - } - sii->in_count = 0; - } - - len = regs->sii_dma_len; - regs->sii_dma_len = 0;/*later?*/ - - /* if dma is still in progress we have to quiet it down */ - cmd = regs->sii_cmd; - if (cmd & SII_CMD_DMA) { - regs->sii_cmd = cmd & ~(SII_CMD_DMA|SII_CMD_XFER); - wbflush(); - /* DONE might NOT pop up. Sigh. */ - delay(10); - regs->sii_data_csr = regs->sii_data_csr; - } - - regs->sii_cmd = SCSI_PHASE_STATUS|SII_CON_CON|(cs & SII_CON_DST); - wbflush(); - - ds = sii_wait(®s->sii_data_csr, SII_DTR_IBF,1); - status.bits = regs->sii_data; - - if (status.st.scsi_status_code != SCSI_ST_GOOD) { - scsi_error(sii->active_target, SCSI_ERR_STATUS, status.bits, 0); - sii->done = (status.st.scsi_status_code == SCSI_ST_BUSY) ? - SCSI_RET_RETRY : SCSI_RET_NEED_SENSE; - } else - sii->done = SCSI_RET_SUCCESS; - - return TRUE; -} - -boolean_t -sii_dma_in( sii, cs, ds) - register sii_softc_t sii; -{ - register target_info_t *tgt; - register sii_padded_regmap_t *regs = sii->regs; - char *dma_ptr; - register int count; - boolean_t advance_script = TRUE; - - SII_COMMAND(regs,cs,ds,0); - LOG(0xE,"dma_in"); - - tgt = sii->active_target; - sii->error_handler = tgt->transient_state.handler; - sii->state |= SII_STATE_DMA_IN; - - if (sii->in_count == 0) { - /* - * Got nothing yet: either just sent the command - * or just reconnected - */ - register int avail; - - if (tgt->transient_state.isa_oddbb) { - regs->sii_dma_1st_byte = tgt->transient_state.oddbb; - tgt->transient_state.isa_oddbb = FALSE; - } - - count = tgt->transient_state.in_count; - count = u_min(count, (SII_DMA_COUNT_MASK+1)); - avail = PER_TGT_BUFF_SIZE - tgt->transient_state.dma_offset; - count = u_min(count, avail); - - /* common case of 8k-or-less read ? */ - advance_script = (tgt->transient_state.in_count == count); - - } else { - - /* - * We received some data. - * Also, take care of bogus interrupts - */ - register int offset, xferred; - unsigned char obb = regs->sii_data; - - xferred = sii->in_count - regs->sii_dma_len; - assert(xferred > 0); - tgt->transient_state.in_count -= xferred; - assert(tgt->transient_state.in_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - count = u_min(tgt->transient_state.in_count, (SII_DMA_COUNT_MASK+1)); - if (tgt->transient_state.dma_offset == PER_TGT_BUFF_SIZE) { - tgt->transient_state.dma_offset = 0; - } else { - register int avail; - avail = PER_TGT_BUFF_SIZE - tgt->transient_state.dma_offset; - count = u_min(count, avail); - } - - /* get some more */ - dma_ptr = tgt->dma_ptr + (tgt->transient_state.dma_offset << 1); - sii->in_count = count; - regs->sii_dma_len = count; - regs->sii_dma_adr_low = SII_DMADR_LO(dma_ptr); - regs->sii_dma_adr_hi = SII_DMADR_HI(dma_ptr); - wbflush(); - regs->sii_cmd = sii->script->command; - wbflush(); - - /* copy what we got */ - careful_copyin_gap16( tgt, offset, xferred, ds & SII_DTR_OBB, obb); - - /* last chunk ? */ - if (count == tgt->transient_state.in_count) { - sii->script++; - } - return FALSE; - } -quickie: - sii->in_count = count; - dma_ptr = tgt->dma_ptr + (tgt->transient_state.dma_offset << 1); - regs->sii_dma_len = count; - regs->sii_dma_adr_low = SII_DMADR_LO(dma_ptr); - regs->sii_dma_adr_hi = SII_DMADR_HI(dma_ptr); - wbflush(); - - if (!advance_script) { - regs->sii_cmd = sii->script->command; - wbflush(); - } - return advance_script; -} - -/* send data to target. Called in three different ways: - (a) to start transfer (b) to restart a bigger-than-8k - transfer (c) after reconnection - */ -boolean_t -sii_dma_out( sii, cs, ds) - register sii_softc_t sii; -{ - register sii_padded_regmap_t *regs = sii->regs; - register char *dma_ptr; - register target_info_t *tgt; - boolean_t advance_script = TRUE; - int count = sii->out_count; - - SII_COMMAND(regs,cs,ds,0); - LOG(0xF,"dma_out"); - - tgt = sii->active_target; - sii->error_handler = tgt->transient_state.handler; - sii->state &= ~SII_STATE_DMA_IN; - - if (sii->out_count == 0) { - /* - * Nothing committed: either just sent the - * command or reconnected - */ - register int remains; - - count = tgt->transient_state.out_count; - count = u_min(count, (SII_DMA_COUNT_MASK+1)); - remains = PER_TGT_BUFF_SIZE - tgt->transient_state.dma_offset; - count = u_min(count, remains); - - /* common case of 8k-or-less write ? */ - advance_script = (tgt->transient_state.out_count == count); - } else { - /* - * We sent some data. - * Also, take care of bogus interrupts - */ - register int offset, xferred; - - xferred = sii->out_count - regs->sii_dma_len; - assert(xferred > 0); - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - count = u_min(tgt->transient_state.out_count, (SII_DMA_COUNT_MASK+1)); - if (tgt->transient_state.dma_offset == PER_TGT_BUFF_SIZE) { - tgt->transient_state.dma_offset = 0; - } else { - register int remains; - remains = PER_TGT_BUFF_SIZE - tgt->transient_state.dma_offset; - count = u_min(count, remains); - } - /* last chunk ? */ - if (tgt->transient_state.out_count == count) - goto quickie; - - /* ship some more */ - dma_ptr = tgt->dma_ptr + - ((tgt->transient_state.cmd_count + tgt->transient_state.dma_offset) << 1); - sii->out_count = count; - regs->sii_dma_len = count; - regs->sii_dma_adr_low = SII_DMADR_LO(dma_ptr); - regs->sii_dma_adr_hi = SII_DMADR_HI(dma_ptr); - wbflush(); - regs->sii_cmd = sii->script->command; - - /* copy some more data */ - careful_copyout_gap16(tgt, offset, xferred); - return FALSE; - } - -quickie: - sii->out_count = count; - dma_ptr = tgt->dma_ptr + - ((tgt->transient_state.cmd_count + tgt->transient_state.dma_offset) << 1); - regs->sii_dma_len = count; - regs->sii_dma_adr_low = SII_DMADR_LO(dma_ptr); - regs->sii_dma_adr_hi = SII_DMADR_HI(dma_ptr); - wbflush(); - - if (!advance_script) { - regs->sii_cmd = sii->script->command; - wbflush(); - } - return advance_script; -} - -/* disconnect-reconnect ops */ - -/* get the message in via dma */ -boolean_t -sii_msg_in(sii, cs, ds) - register sii_softc_t sii; - register unsigned char cs, ds; -{ - register target_info_t *tgt; - char *dma_ptr; - register sii_padded_regmap_t *regs = sii->regs; - - LOG(0x15,"msg_in"); - - tgt = sii->active_target; - - dma_ptr = tgt->dma_ptr; - /* We would clobber the data for READs */ - if (sii->state & SII_STATE_DMA_IN) { - register int offset; - offset = tgt->transient_state.cmd_count + tgt->transient_state.dma_offset; - if (offset & 1) offset++; - dma_ptr += (offset << 1); - } - - regs->sii_dma_adr_low = SII_DMADR_LO(dma_ptr); - regs->sii_dma_adr_hi = SII_DMADR_HI(dma_ptr); - /* We only really expect two bytes */ - regs->sii_dma_len = sizeof(scsi_command_group_0); - wbflush(); - - return TRUE; -} - -/* check the message is indeed a DISCONNECT */ -boolean_t -sii_disconnect(sii, cs, ds) - register sii_softc_t sii; - register unsigned char cs, ds; - -{ - register target_info_t *tgt; - register int len; - boolean_t ok = FALSE; - unsigned int dmsg = 0; - - tgt = sii->active_target; - - len = sizeof(scsi_command_group_0) - sii->regs->sii_dma_len; - PRINT(("{G%d}",len)); - -/* if (len == 0) ok = FALSE; */ - if (len == 1) { - dmsg = sii->regs->sii_dma_1st_byte; - ok = (dmsg == SCSI_DISCONNECT); - } else if (len == 2) { - register char *msgs; - register unsigned int offset; - register sii_padded_regmap_t *regs = sii->regs; - - /* wherever it was, take it from there */ - offset = regs->sii_dma_adr_low | ((regs->sii_dma_adr_hi&3)<<16); - msgs = (char*)sii->buff + (offset << 1); - dmsg = *((unsigned short *)msgs); - - /* A SDP message preceeds it in non-completed READs */ - ok = (((dmsg & 0xff) == SCSI_DISCONNECT) || - (dmsg == ((SCSI_DISCONNECT<<8)|SCSI_SAVE_DATA_POINTER))); - } - if (!ok) - printf("[tgt %d bad msg (%d): %x]", tgt->target_id, len, dmsg); - - return TRUE; -} - -/* save all relevant data, free the BUS */ -boolean_t -sii_disconnected(sii, cs, ds) - register sii_softc_t sii; - register unsigned char cs, ds; - -{ - register target_info_t *tgt; - - SII_COMMAND(sii->regs,cs,ds,0); - - sii->regs->sii_csr = SII_CSR_IE|SII_CSR_PCE|SII_CSR_SLE| - SII_CSR_HPM|SII_CSR_RSE; - - LOG(0x16,"disconnected"); - - sii_disconnect(sii,cs,ds); - - tgt = sii->active_target; - tgt->flags |= TGT_DISCONNECTED; - tgt->transient_state.handler = sii->error_handler; - /* the rest has been saved in sii_err_disconn() */ - - PRINT(("{D%d}", tgt->target_id)); - - sii_release_bus(sii); - - return FALSE; -} - -/* get reconnect message, restore BUS */ -boolean_t -sii_reconnect(sii, cs, ds) - register sii_softc_t sii; - register unsigned char cs, ds; - -{ - register target_info_t *tgt; - sii_padded_regmap_t *regs; - int id; - - regs = sii->regs; - regs->sii_conn_csr = SII_CON_SCH; - regs->sii_cmd = SII_CON_CON|SII_CON_DST|SCSI_PHASE_MSG_IN; - wbflush(); - - LOG(0x17,"reconnect"); - - /* - * See if this reconnection collided with a selection attempt - */ - if (sii->state & SII_STATE_BUSY) - sii->state |= SII_STATE_COLLISION; - - sii->state |= SII_STATE_BUSY; - - cs = regs->sii_conn_csr; - - /* tk50s are slow */ - if ((cs & SII_CON_CON) == 0) - cs = sii_wait(®s->sii_conn_csr, SII_CON_CON,1); - - /* ?? */ - if (regs->sii_conn_csr & SII_CON_BERR) - regs->sii_conn_csr = SII_CON_BERR; - - if ((ds & SII_DTR_IBF) == 0) - ds = sii_wait(®s->sii_data_csr, SII_DTR_IBF,1); - - if (regs->sii_data != SCSI_IDENTIFY) - printf("{I%x %x}", regs->sii_data, regs->sii_dma_1st_byte); - - /* find tgt: id is in sii_destat */ - id = regs->sii_destat; - - tgt = sii->sc->target[id]; - if (id > 7 || tgt == 0) panic("sii_reconnect"); - - PRINT(("{R%d}", id)); - if (sii->state & SII_STATE_COLLISION) - PRINT(("[B %d-%d]", sii->active_target->target_id, id)); - - LOG(0x80+id,0); - - sii->active_target = tgt; - tgt->flags &= ~TGT_DISCONNECTED; - - /* synch params */ - regs->sii_dma_ctrl = tgt->sync_offset; - regs->sii_dma_len = 0; - - sii->script = tgt->transient_state.script; - sii->error_handler = sii_err_rdp; - sii->in_count = 0; - sii->out_count = 0; - - regs->sii_cmd = SII_CMD_XFER|SII_CMD_CON|SII_CMD_DST|SCSI_PHASE_MSG_IN; - wbflush(); - - (void) sii_wait(®s->sii_data_csr, SII_DTR_DONE,1); - regs->sii_data_csr = SII_DTR_DONE; - - return TRUE; -} - - -/* do the synch negotiation */ -boolean_t -sii_dosynch( sii, cs, ds) - register sii_softc_t sii; -{ - /* - * Phase is MSG_OUT here, cmd has not been xferred - */ - int *p, len; - unsigned short dmalo, dmahi, dmalen; - register target_info_t *tgt; - register sii_padded_regmap_t *regs = sii->regs; - unsigned char off; - - regs->sii_cmd = SCSI_PHASE_MSG_OUT|SII_CMD_ATN|SII_CON_CON; - wbflush(); - - LOG(0x11,"dosync"); - - tgt = sii->active_target; - - tgt->flags |= TGT_DID_SYNCH; /* only one chance */ - tgt->flags &= ~TGT_TRY_SYNCH; - - p = (int*) (tgt->dma_ptr + (((regs->sii_dma_len<<1) + 2) & ~3)); - p[0] = SCSI_IDENTIFY | (SCSI_EXTENDED_MESSAGE<<8); - p[1] = 3 | (SCSI_SYNC_XFER_REQUEST<<8); - if (BGET(scsi_no_synchronous_xfer,tgt->masterno,tgt->target_id)) - off = 0; - else - off = sii_max_offset; - /* but we'll ship "off" manually */ - p[2] = sii_to_scsi_period(sii_min_period) |(off << 8); - - dmalen = regs->sii_dma_len; - dmalo = regs->sii_dma_adr_low; - dmahi = regs->sii_dma_adr_hi; - regs->sii_dma_len = sizeof(scsi_synch_xfer_req_t) /* + 1 */; - regs->sii_dma_adr_low = SII_DMADR_LO(p); - regs->sii_dma_adr_hi = SII_DMADR_HI(p); - wbflush(); - - regs->sii_cmd = SII_CMD_DMA|SII_CMD_XFER|SII_CMD_ATN| - SII_CON_CON|SCSI_PHASE_MSG_OUT; - wbflush(); - - /* wait for either DONE or MIS */ - ds = sii_wait(®s->sii_data_csr, SII_DTR_DI,1); - - /* TK50s do not like xtended messages */ - /* and some others just ignore the standard */ - if (SCSI_PHASE(ds) != SCSI_PHASE_MSG_OUT) { - /* disentangle FIFO */ - regs->sii_cmd = SII_CON_CON|SCSI_PHASE_MSG_OUT; - ds = sii_wait(®s->sii_data_csr, SII_DTR_DONE,1); - if (SCSI_PHASE(ds) == SCSI_PHASE_MSG_IN) - goto msgin; - goto got_answer; - } - - /* ack and stop dma */ - regs->sii_cmd = SII_CON_CON|SCSI_PHASE_MSG_OUT|SII_CMD_ATN; - wbflush(); - ds = sii_wait(®s->sii_data_csr, SII_DTR_DONE,1); - regs->sii_data_csr = SII_DTR_DONE; - wbflush(); - - /* last byte of message */ - regs->sii_data = off; - wbflush(); - regs->sii_cmd = SII_CMD_XFER|SII_CON_CON|SCSI_PHASE_MSG_OUT; - wbflush(); - - /* Race here: who will interrupt first, the DMA - controller or the status watching machine ? */ - delay(1000); - regs->sii_cmd = SII_CON_CON|SCSI_PHASE_MSG_OUT; - wbflush(); - - ds = sii_wait(®s->sii_data_csr, SII_DTR_DONE,1); - regs->sii_data_csr = SII_DTR_DONE; - - /* The standard sez there nothing else the target can do but.. */ - ds = sii_wait(®s->sii_data_csr, SCSI_PHASE_MSG_IN,0); - - /* Of course, what are standards for ? */ - if (SCSI_PHASE(ds) == SCSI_PHASE_CMD) - goto cmdp; -msgin: - /* ack */ - regs->sii_cmd = SII_CON_CON|SCSI_PHASE_MSG_IN; - wbflush(); - - /* set up dma to receive answer */ - regs->sii_dma_adr_low = SII_DMADR_LO(p); - regs->sii_dma_adr_hi = SII_DMADR_HI(p); - regs->sii_dma_len = sizeof(scsi_synch_xfer_req_t); - wbflush(); - regs->sii_cmd = SII_CMD_DMA|SII_CMD_XFER|SII_CON_CON|SCSI_PHASE_MSG_IN; - wbflush(); - - /* wait for the answer, and look at it */ - ds = sii_wait(®s->sii_data_csr, SII_DTR_MIS,1); - - regs->sii_cmd = SII_CON_CON|SCSI_PHASE_MSG_IN; - wbflush(); - ds = sii_wait(®s->sii_data_csr, SII_DTR_DONE,1); - -got_answer: - /* do not cancel the phase mismatch */ - regs->sii_data_csr = SII_DTR_DONE; - - if (regs->sii_dma_len || ((p[0] & 0xff) != SCSI_EXTENDED_MESSAGE)) { - /* did not like it */ - printf(" did not like SYNCH xfer "); - } else { - /* will do synch */ - tgt->sync_period = scsi_period_to_sii((p[1]>>8)&0xff); - tgt->sync_offset = regs->sii_data; /* odd xfer, in silo */ - /* sanity */ - if (tgt->sync_offset > sii_max_offset) - tgt->sync_offset = sii_max_offset; - regs->sii_dma_ctrl = tgt->sync_offset; - } - -cmdp: - /* phase should be command now */ - regs->sii_dma_len = dmalen; - regs->sii_dma_adr_low = dmalo; - regs->sii_dma_adr_hi = dmahi; - wbflush(); - - /* continue with simple command script */ - sii->error_handler = sii_err_generic; - - sii->script = (tgt->cur_cmd == SCSI_CMD_INQUIRY) ? - sii_script_data_in : sii_script_cmd; - if (SCSI_PHASE(ds) == SCSI_PHASE_CMD ) - return TRUE; - - sii->script++; - if (SCSI_PHASE(ds) == SCSI_PHASE_STATUS ) - return TRUE; - - sii->script++; /* msgin? */ - sii->script++; - if (SCSI_PHASE(ds) == SII_PHASE_DISC) - return TRUE; - -gimmeabreak(); - panic("sii_dosynch"); - return FALSE; -} - -/* - * The bus was reset - */ -sii_bus_reset(sii) - register sii_softc_t sii; -{ - register sii_padded_regmap_t *regs = sii->regs; - - LOG(0x21,"bus_reset"); - - /* - * Clear interrupt bits - */ - regs->sii_conn_csr = 0xffff; - regs->sii_data_csr = 0xffff; - - /* - * Clear bus descriptor - */ - sii->script = 0; - sii->error_handler = 0; - sii->active_target = 0; - sii->next_target = 0; - sii->state = 0; - queue_init(&sii->waiting_targets); - sii->wd.nactive = 0; - sii_reset(regs, TRUE); - - log(LOG_KERN, "sii: (%d) bus reset ", ++sii->wd.reset_count); - delay(scsi_delay_after_reset); /* some targets take long to reset */ - - if (sii->sc == 0) /* sanity */ - return; - - sii_inside_sii_intr = FALSE; - - scsi_bus_was_reset(sii->sc); -} - -/* - * Error handlers - */ - -/* - * Generic, default handler - */ -boolean_t -sii_err_generic(sii, cs, ds) - register sii_softc_t sii; -{ - register int cond = sii->script->condition; - - LOG(0x10,"err_generic"); - - /* - * Note to DEC hardware people. - * Dropping the notion of interrupting on - * DMA completions (or at least make it optional) - * would save TWO interrupts out of the SEVEN that - * are currently requested for a non-disconnecting - * READ or WRITE operation. - */ - if (ds & SII_DTR_DONE) - return TRUE; - - /* this is a band-aid */ - if ((SCSI_PHASE(cond) == SII_PHASE_DISC) && - (cs & SII_CON_SCH)) { - ds &= ~7; - ds |= SII_PHASE_DISC; - (void) (*sii->script->action)(sii,cs,ds); - return FALSE; - } - - /* TK50s are slow to connect, forgive em */ - if ((SCSI_PHASE(ds) == SCSI_PHASE_MSG_OUT) || - (SCSI_PHASE(cond) == SCSI_PHASE_MSG_OUT)) - return TRUE; - if ((SCSI_PHASE(cond) == SCSI_PHASE_CMD) && - ((SCSI_PHASE(ds) == 0) || (SCSI_PHASE(ds) == 4) || (SCSI_PHASE(ds) == 5))) - return TRUE; - - /* transition to status ? */ - if (SCSI_PHASE(ds) == SCSI_PHASE_STATUS) - return sii_err_to_status(sii, cs, ds); - - return sii_err_phase_mismatch(sii,cs,ds); -} - -/* - * Handle generic errors that are reported as - * an unexpected change to STATUS phase - */ -sii_err_to_status(sii, cs, ds) - register sii_softc_t sii; -{ - script_t scp = sii->script; - - LOG(0x20,"err_tostatus"); - while (SCSI_PHASE(scp->condition) != SCSI_PHASE_STATUS) - scp++; - sii->script = scp; -#if 0 - /* - * Normally, we would already be able to say the command - * is in error, e.g. the tape had a filemark or something. - * But in case we do disconnected mode WRITEs, it is quite - * common that the following happens: - * dma_out -> disconnect -> reconnect - * and our script might expect at this point that the dma - * had to be restarted (it didn't know it was completed - * because the tape record is shorter than we asked for). - * And in any event.. it is both correct and cleaner to - * declare error iff the STATUS byte says so. - */ - sii->done = SCSI_RET_NEED_SENSE; -#endif - return TRUE; -} - -/* - * Watch for a disconnection - */ -boolean_t -sii_err_disconn(sii, cs, ds) - register sii_softc_t sii; - register unsigned cs, ds; -{ - register sii_padded_regmap_t *regs; - register target_info_t *tgt; - int count; - int from; - unsigned char obb; - int delayed_copy = 0; - - LOG(0x18,"err_disconn"); - - if (SCSI_PHASE(ds) != SCSI_PHASE_MSG_IN) - return sii_err_generic(sii, cs, ds); - - regs = sii->regs; - - if ((regs->sii_cmd & (SII_CMD_DMA|SII_CMD_XFER)) == - (SII_CMD_DMA|SII_CMD_XFER)) { - /* stop dma and wait */ - regs->sii_cmd &= ~(SII_CMD_DMA|SII_CMD_XFER); - (void) sii_wait(®s->sii_data_csr, SII_DTR_DONE,1); -/* later: regs->sii_data_csr = SII_DTR_DONE; */ - } - - SII_COMMAND(regs,cs,ds,0); - - tgt = sii->active_target; - switch (SCSI_PHASE(sii->script->condition)) { - case SCSI_PHASE_DATAO: - LOG(0x1b,"+DATAO"); - if (sii->out_count) { - register int xferred, offset; - - xferred = sii->out_count - regs->sii_dma_len; - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - if (tgt->transient_state.dma_offset == PER_TGT_BUFF_SIZE) - tgt->transient_state.dma_offset = 0; - - delayed_copy = 1; - from = offset; - count = xferred; - - } - tgt->transient_state.script = sii_script_restart_data_out; - break; - - case SCSI_PHASE_DATAI: - LOG(0x19,"+DATAI"); - if (sii->in_count) { - register int offset, xferred; - - obb = regs->sii_dma_1st_byte; - - xferred = sii->in_count - regs->sii_dma_len; - assert(xferred > 0); - if (ds & SII_DTR_OBB) { - tgt->transient_state.isa_oddbb = TRUE; - tgt->transient_state.oddbb = obb; - } - tgt->transient_state.in_count -= xferred; - assert(tgt->transient_state.in_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - if (tgt->transient_state.dma_offset == PER_TGT_BUFF_SIZE) - tgt->transient_state.dma_offset = 0; - - /* copy what we got */ - - delayed_copy = 2; - from = offset; - count = xferred; - - } - tgt->transient_state.script = sii_script_restart_data_in; - break; - - case SCSI_PHASE_STATUS: - /* will have to restart dma */ - if (count = regs->sii_dma_len) { - (void) sii_wait(®s->sii_data_csr, SII_DTR_DONE,1); - regs->sii_data_csr = SII_DTR_DONE; - } - if (sii->state & SII_STATE_DMA_IN) { - register int offset, xferred; - - obb = regs->sii_dma_1st_byte; - - LOG(0x1a,"+STATUS+R"); - - xferred = sii->in_count - count; - assert(xferred > 0); - if (ds & SII_DTR_OBB) { - tgt->transient_state.isa_oddbb = TRUE; - tgt->transient_state.oddbb = obb; - } - tgt->transient_state.in_count -= xferred; -/* assert(tgt->transient_state.in_count > 0);*/ - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - if (tgt->transient_state.dma_offset == PER_TGT_BUFF_SIZE) - tgt->transient_state.dma_offset = 0; - - /* copy what we got */ - - delayed_copy = 2; - from = offset; - count = xferred; - - tgt->transient_state.script = sii_script_restart_data_in; - if (tgt->transient_state.in_count == 0) - tgt->transient_state.script++; - - } else { - - LOG(0x1d,"+STATUS+W"); - - if ((count == 0) && (tgt->transient_state.out_count == sii->out_count)) { - /* all done */ - tgt->transient_state.script = &sii_script_restart_data_out[1]; - tgt->transient_state.out_count = 0; - } else { - register int xferred, offset; - - /* how much we xferred */ - xferred = sii->out_count - count; - - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - if (tgt->transient_state.dma_offset == PER_TGT_BUFF_SIZE) - tgt->transient_state.dma_offset = 0; - - delayed_copy = 1; - from = offset; - count = xferred; - - tgt->transient_state.script = sii_script_restart_data_out; - } - sii->out_count = 0; - } - break; - case SII_PHASE_DISC: /* sometimes disconnects and phase remains */ - return sii_err_generic(sii, cs, ds); - default: - gimmeabreak(); - } - regs->sii_csr &= ~SII_CSR_RSE; - sii_msg_in(sii,cs,ds); - sii->script = sii_script_disconnect; - regs->sii_cmd = SII_CMD_DMA|SII_CMD_XFER|SCSI_PHASE_MSG_IN| - SII_CON_CON|(regs->sii_conn_csr & SII_CON_DST); - wbflush(); - if (delayed_copy == 2) - careful_copyin_gap16( tgt, from, count, ds & SII_DTR_OBB, obb); - else if (delayed_copy == 1) - careful_copyout_gap16( tgt, from, count); - - return FALSE; -} - -/* - * Suppose someone reads the specs as they read the Bible. - * They would send these unnecessary restore-pointer msgs - * in reconnect phases. If this was a SCSI-2 modify-pointer - * I could understand, but. Oh well. - */ -sii_err_rdp(sii, cs, ds) - register sii_softc_t sii; -{ - register sii_padded_regmap_t *regs; - register target_info_t *tgt; - - LOG(0x24,"err_drp"); - - /* One chance */ - sii->error_handler = sii->active_target->transient_state.handler; - - if (SCSI_PHASE(ds) != SCSI_PHASE_MSG_IN) - return sii_err_generic(sii, cs, ds); - - regs = sii->regs; - - if ((ds & SII_DTR_IBF) == 0) - ds = sii_wait(®s->sii_data_csr, SII_DTR_IBF,1); - - if (regs->sii_data != SCSI_RESTORE_POINTERS) - return sii_err_disconn(sii, cs, ds); - - regs->sii_cmd = SII_CMD_XFER|SII_CMD_CON|SII_CMD_DST|SCSI_PHASE_MSG_IN; - wbflush(); - - (void) sii_wait(®s->sii_data_csr, SII_DTR_DONE,1); - regs->sii_data_csr = SII_DTR_DONE; - - return FALSE; -} - -/* - * Handle strange, yet unexplained interrupts and error - * situations which eventually I will be old and wise - * enough to deal with properly with preventive care. - */ -sii_err_phase_mismatch(sii, cs, ds) - register sii_softc_t sii; -{ - register sii_padded_regmap_t *regs = sii->regs; - register int match; - - LOG(0x23,"err_mismatch"); - - match = SCSI_PHASE(sii->script->condition); - - /* dmain interrupted */ - if ((match == SCSI_PHASE_STATUS) && (SCSI_PHASE(ds) == SCSI_PHASE_DATAI)) { - register int xferred; - register char *p; - - if (regs->sii_dma_len <= 1) { -/*if (scsi_debug)*/ -printf("[DMAINZERO %x %x %x]", cs, ds, regs->sii_dma_len); - if (regs->sii_dma_len == 0) { - regs->sii_dma_len = sii->in_count; - wbflush(); - regs->sii_cmd = sii->script[-1].command; - } - return FALSE; - } - - /* This happens when you do not "init" the prom - and the fifo is screwed up */ - xferred = sii->in_count - regs->sii_dma_len; - p = (char*)( regs->sii_dma_adr_low | ((regs->sii_dma_adr_hi&3)<<16) ); - p += xferred; -if (scsi_debug) -printf("[DMAIN %x %x %x]", cs, ds, xferred); - /* odd bytes are not xferred */ - if (((unsigned)p) & 0x1){ - register short *oddb; - oddb = (short*)(sii->buff) + ((unsigned)p-1);/*shifts*/ - *oddb = regs->sii_dma_1st_byte; - } - regs->sii_dma_adr_low = ((unsigned)p); - regs->sii_dma_adr_hi = ((unsigned)p) << 16; - wbflush(); - regs->sii_cmd = sii->script[-1].command; - wbflush(); - return FALSE; - } else - /* dmaout interrupted */ - if ((match == SCSI_PHASE_STATUS) && (SCSI_PHASE(ds) == SCSI_PHASE_DATAO)) { - register int xferred; - register char *p; - - if (regs->sii_dma_len <= 1) { -/*if (scsi_debug)*/ -printf("[DMAOUTZERO %x %x %x]", cs, ds, regs->sii_dma_len); -gimmeabreak(); - if (regs->sii_dma_len == 0) { - regs->sii_dma_len = sii->out_count; - wbflush(); - regs->sii_cmd = sii->script[-1].command; - } - return FALSE; - } - - xferred = sii->out_count - regs->sii_dma_len; -/*if (scsi_debug)*/ -printf("[DMAOUT %x %x %x %x]", cs, ds, regs->sii_dma_len, sii->out_count); - sii->out_count -= xferred; - p = (char*)( regs->sii_dma_adr_low | ((regs->sii_dma_adr_hi&3)<<16) ); - p += xferred; - regs->sii_dma_adr_low = ((unsigned)p); - regs->sii_dma_adr_hi = ((unsigned)p) << 16; - wbflush(); - regs->sii_cmd = sii->script[-1].command; - wbflush(); - return FALSE; - } -#if 1 /* ?? */ - /* stuck in cmd phase */ - else if ((SCSI_PHASE(ds) == SCSI_PHASE_CMD) && - ((match == SCSI_PHASE_DATAI) || (match == SCSI_PHASE_DATAO))) { -/*if (scsi_debug)*/ -printf("[CMD %x %x %x %x]", cs, ds, sii->cmd_count, regs->sii_dma_len); - if (regs->sii_dma_len != 0) { - /* ouch, this hurts */ - register int xferred; - register char *p; - - xferred = sii->cmd_count - regs->sii_dma_len; - sii->cmd_count -= xferred; - p = (char*)( regs->sii_dma_adr_low | ((regs->sii_dma_adr_hi&3)<<16) ); - p += xferred; - regs->sii_dma_adr_low = ((unsigned)p); - regs->sii_dma_adr_hi = ((unsigned)p) << 16; - wbflush(); - regs->sii_cmd = 0x8842; - wbflush(); - return FALSE;; - - } - SII_ACK(regs,cs,ds,0/*match*/); - wbflush(); - return FALSE;; - } -#endif - else { - printf("{D%x %x}", cs, ds); -/* if (scsi_debug)*/ gimmeabreak(); - } - return FALSE; -} - -/* - * Watchdog - * - * There are two ways in which I have seen the chip - * get stuck: a target never reconnected, or the - * selection deadlocked. Both cases involved a tk50, - * but elsewhere it showed up with hitachi disks too. - */ -sii_reset_scsibus(sii) - register sii_softc_t sii; -{ - register target_info_t *tgt = sii->active_target; - register sii_padded_regmap_t *regs = sii->regs; - - /* see if SIP still --> device down or non-existant */ - if ((regs->sii_conn_csr & (SII_CON_LST|SII_CON_SIP)) == SII_CON_SIP){ - if (tgt) { - log(LOG_KERN, "Target %d went offline\n", - tgt->target_id); - tgt->flags = 0; - return sii_probe_timeout(tgt); - } - /* else fall through */ - } - - if (tgt) - log(LOG_KERN, "Target %d was active, cmd x%x in x%x out x%x Sin x%x Sou x%x dmalen x%x\n", - tgt->target_id, tgt->cur_cmd, - tgt->transient_state.in_count, tgt->transient_state.out_count, - sii->in_count, sii->out_count, - sii->regs->sii_dma_len); - - sii->regs->sii_cmd = SII_CMD_RST; - delay(25); -} - -/* - * Copy routines that avoid odd pointers - */ -boolean_t nocopyin = FALSE; -careful_copyin_gap16(tgt, offset, len, isaobb, obb) - register target_info_t *tgt; - unsigned char obb; -{ - register char *from, *to; - register int count; - - count = tgt->transient_state.copy_count; - - from = tgt->dma_ptr + (offset << 1); - to = tgt->ior->io_data + count; - tgt->transient_state.copy_count = count + len; - if (count & 1) { - from -= (1 << 1); - to -= 1; - len += 1; - } -if (nocopyin) return;/*timing*/ - copyin_gap16( from, to, len); - /* check for last, poor little odd byte */ - if (isaobb) { - to += len; - to[-1] = obb; - } -} - -careful_copyout_gap16( tgt, offset, len) - register target_info_t *tgt; -{ - register char *from, *to; - register int count, olen; - unsigned char c; - char *p; - - count = tgt->ior->io_count - tgt->transient_state.copy_count; - if (count > 0) { - - len = u_min(count, len); - offset += tgt->transient_state.cmd_count; - - count = tgt->transient_state.copy_count; - tgt->transient_state.copy_count = count + len; - - from = tgt->ior->io_data + count; - to = tgt->dma_ptr + (offset << 1); - - /* the scsi buffer acts weirdo at times */ - if ((olen=len) & 1) { - p = tgt->dma_ptr + ((offset + olen - 1)<<1); - c = (*(unsigned short*)p) >> 8;/*!MSF*/ - } - - if (count & 1) { - from -= 1; - to -= (1 << 1); - len += 1; - } - - count = copyout_gap16(from, to, len); - - /* the scsi buffer acts weirdo at times */ - if (olen & 1) { - unsigned char cv; - cv = (*(unsigned short*)p) >> 8;/*!MSF*/ - if (c != cv) { - /* - * Scott Fahlman would say - * "Use a big plier!" - */ - unsigned short s; - volatile unsigned short *pp; - pp = (volatile unsigned short*)p; - s = (c << 8) | (from[len-1] & 0xff); - do { - *pp = s; - } while (*pp != s); - } - } - } -} - -#endif NSII > 0 - diff --git a/scsi/adapters/scsi_89352.h b/scsi/adapters/scsi_89352.h deleted file mode 100644 index 85c579f..0000000 --- a/scsi/adapters/scsi_89352.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_89352.h - * Author: Daniel Stodolsky, Carnegie Mellon University - * Date: 06/91 - * - * Defines for the Fujitsu MB89352 SCSI Protocol Controller (HBA) - * The definitions herein also cover the 89351, 87035/36, 87033B - */ - -/* - * Register map, padded as needed. Matches Hardware, do not screw up. - */ - -#define vuc volatile unsigned char - -typedef struct -{ - vuc spc_bdid; /* Bus Device ID (R/W) */ -#define spc_myid spc_bdid - char pad0[3]; - vuc spc_sctl; /* SPC Control register (R/W) */ - char pad1[3]; - vuc spc_scmd; /* Command Register (R/W) */ - char pad2[3]; - vuc spc_tmod; /* Transmit Mode Register (synch models) */ - char pad3[3]; - vuc spc_ints; /* Interrupt sense (R); Interrupt Reset (w) */ - char pad4[3]; - vuc spc_psns; /* Phase Sense (R); SPC Diagnostic Control (w) */ -#define spc_phase spc_psns - char pad5[3]; - vuc spc_ssts; /* SPC status (R/O) */ - char pad6[3]; - vuc spc_serr; /* SPC error status (R/O) */ - char pad7[3]; - vuc spc_pctl; /* Phase Control (R/W) */ - char pad8[3]; - vuc spc_mbc; /* Modifed Byte Counter (R/O) */ - char pad9[3]; - vuc spc_dreg; /* Data Register (R/W) */ - char pad10[3]; - vuc spc_temp; /* Temporary Register (R/W) */ - char pad11[3]; - vuc spc_tch; /* Transfer Counter High (R/W) */ - char pad12[3]; - vuc spc_tcm; /* Transfer Counter Middle (R/W) */ - char pad13[3]; - vuc spc_tcl; /* Transfer Counter Low (R/W) */ - char pad14[3]; - vuc spc_exbf; /* External Buffer (synch models) */ - char pad15[3]; -} spc_regmap_t; - -#undef vuc - -/* - * Control register - */ - -#define SPC_SCTL_DISABLE 0x80 -#define SPC_SCTL_RESET 0x40 -#define SPC_SCTL_DIAGMODE 0x20 -#define SPC_SCTL_ARB_EBL 0x10 -#define SPC_SCTL_PAR_EBL 0x08 -#define SPC_SCTL_SEL_EBL 0x04 -#define SPC_SCTL_RSEL_EBL 0x02 -#define SPC_SCTL_IE 0x01 - -/* - * Command register - */ - -#define SPC_SCMD_CMDMASK 0xe0 -# define SPC_SCMD_C_ACKREQ_S 0xe0 -# define SPC_SCMD_C_ACKREQ_C 0xc0 -# define SPC_SCMD_C_STOP_X 0xa0 -# define SPC_SCMD_C_XFER 0x80 -# define SPC_SCMD_C_ATN_S 0x60 -# define SPC_SCMD_C_ATN_C 0x40 -# define SPC_SCMD_C_SELECT 0x20 -# define SPC_SCMD_C_BUS_RLSE 0x00 -#define SPC_SCMD_BUSRST 0x10 -#define SPC_SCMD_INTERCEPT_X 0x08 -#define SPC_SCMD_PROGRAMMED_X 0x04 -#define SPC_SCMD_PAD_X 0x01 - -/* - * Transfer mode register (MB87033B/35/36) - */ - -#define SPC_TMOD_SYNC_X 0x80 -#define SPC_TMOD_OFFSET_MASK 0x70 -# define SPC_OFFSET(x) (((x)<<4)&SPC_TMOD_OFFSET_MASK) -#define SPC_TMOD_PERIOD_MASK 0xc0 -# define SPC_PERIOD(x) (((x)<<2)&SPC_TMOD_PERIOD_MASK) -#define SPC_TMOD_EXP_COUNTER 0x01 - -/* - * Interrupt cause register - */ - -#define SPC_INTS_SELECTED 0x80 -#define SPC_INTS_RESELECTED 0x40 -#define SPC_INTS_DISC 0x20 -#define SPC_INTS_DONE 0x10 -#define SPC_INTS_BUSREQ 0x08 -#define SPC_INTS_TIMEOUT 0x04 -#define SPC_INTS_ERROR 0x02 -#define SPC_INTS_RESET 0x01 - -/* - * SCSI Bus signals ("phase") - */ - -#define SPC_BUS_REQ 0x80 /* rw */ -#define SPC_BUS_ACK 0x40 /* rw */ -#define SPC_BUS_ATN 0x20 /* ro */ -# define SPC_DIAG_ENBL_XFER 0x20 /* wo */ -#define SPC_BUS_SEL 0x10 /* ro */ -#define SPC_BUS_BSY 0x08 /* rw */ -#define SPC_BUS_MSG 0x04 /* rw */ -#define SPC_BUS_CD 0x02 /* rw */ -#define SPC_BUS_IO 0x01 /* rw */ - -#define SPC_CUR_PHASE(x) SCSI_PHASE(x) - -#define SPC_BSY(r) (r->spc_phase & SPC_BUS_BSY) - -/* - * Chip status register - */ - -#define SPC_SSTS_INI_CON 0x80 -#define SPC_SSTS_TGT_CON 0x40 -#define SPC_SSTS_BUSY 0x20 -#define SPC_SSTS_XIP 0x10 -#define SPC_SSTS_RST 0x08 -#define SPC_SSTS_TC0 0x04 -#define SPC_SSTS_FIFO_FULL 0x02 -#define SPC_SSTS_FIFO_EMPTY 0x01 - -/* - * Error register - */ - -#define SPC_SERR_SEL 0x80 /* Selected */ -#define SPC_SERR_RSEL 0x40 /* Reselected */ -#define SPC_SERR_DISC 0x20 /* Disconnected */ -#define SPC_SERR_CMDC 0x10 /* Command Complete */ -#define SPC_SERR_SRVQ 0x08 /* Service Required */ -#define SPC_SERR_TIMO 0x04 /* Timeout */ -#define SPC_SERR_HARDERR 0x02 /* SPC Hard Error */ -#define SPC_SERR_RSTC 0x01 /* Reset Condition */ - -/* - * Phase control register - * - * [use SPC_CUR_PHASE() here too] - */ - -#define SPC_PCTL_BFREE_IE 0x80 /* Bus free (disconnected) */ -#define SPC_PCTL_LST_IE 0x40 /* lost arbit (87033) */ -#define SPC_PCTL_ATN_IE 0x20 /* ATN set (87033) */ -#define SPC_PCTL_RST_DIS 0x10 /* RST asserted */ - -/* - * Modified byte counter register - */ - -#define SPC_MBC_ECNT_MASK 0xf0 /* 87033 only */ -# define SPC_MBC_ECNT_GET(x) (((x)&SPC_MBC_ECNT_MASK)>>4) -# define SPC_MBC_ECNT_PUT(x) (((x)<<4)&SPC_MBC_ECNT_MASK) -#define SPC_MBC_MBC_MASK 0x0f -# define SPC_MBC_GET(x) ((x)&SPC_MBC_MBC_MASK) -# define SPC_MBC_PUT(x) ((x)&SPC_MBC_MBC_MASK) - -/* - * Transfer counter register(s) - */ - -#define SPC_TC_PUT(ptr,val) { \ - (ptr)->spc_tch = (((val)>>16)&0xff); \ - (ptr)->spc_tcm = (((val)>> 8)&0xff); \ - (ptr)->spc_tcl = (((val) )&0xff); \ - } - -#define SPC_TC_GET(ptr,val) { \ - (val) = (((ptr)->spc_tch & 0xff )<<16) |\ - (((ptr)->spc_tcm 0 0xff )<<8) |\ - ((ptr)->spc_tcl 0xff);\ - } - -/* 87033 in expanded mode */ -#define SPC_XTC_PUT(ptr,val) { \ - (ptr)->spc_mbc = SPC_MBC_ECNT_PUT(((val)>>24));\ - (ptr)->spc_tch = (((val)>>16)&0xff); \ - (ptr)->spc_tcm = (((val)>> 8)&0xff); \ - (ptr)->spc_tcl = (((val) )&0xff); \ - } - -#define SPC_XTC_GET(ptr,val) { \ - (val) = (SPC_MBC_ECNT_GET((ptr)->spc_mbc)<<24)|\ - (((ptr)->spc_tch)<<16)|(((ptr)->spc_tcm)<<8)|\ - ((ptr)->spc_tcl);\ - } - diff --git a/scsi/adapters/scsi_89352_hdw.c b/scsi/adapters/scsi_89352_hdw.c deleted file mode 100644 index 5672cb6..0000000 --- a/scsi/adapters/scsi_89352_hdw.c +++ /dev/null @@ -1,2192 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1992,1991 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_89352_hdw.c - * Author: Daniel Stodolsky, Carnegie Mellon University - * Date: 06/91 - * - * Bottom layer of the SCSI driver: chip-dependent functions - * - * This file contains the code that is specific to the Fujitsu MB89352 - * SCSI chip (Host Bus Adapter in SCSI parlance): probing, start - * operation, and interrupt routine. - */ - -/* - * This layer works based on small simple 'scripts' that are installed - * at the start of the command and drive the chip to completion. - * The idea comes from the specs of the NCR 53C700 'script' processor. - * - * There are various reasons for this, mainly - * - Performance: identify the common (successful) path, and follow it; - * at interrupt time no code is needed to find the current status - * - Code size: it should be easy to compact common operations - * - Adaptability: the code skeleton should adapt to different chips without - * terrible complications. - * - Error handling: and it is easy to modify the actions performed - * by the scripts to cope with strange but well identified sequences - * - */ - -/* - * - * - * Known Headaches/Features with this chip. - * - * (1) After the interrupt raised by select, the phase sense (psns) - * and SPC status (ssts) registers do not display the correct values - * until the REQ line (via psns) is high. (danner@cs.cmu.edu 6/11/91) - * - * (2) After a data in phase, the command complete interrupt may be raised - * before the psns, ssts, and transfer counter registers settle. The reset - * acknowledge or request command should not be issued until they settle. - * (danner@cs.cmu.edu 6/14/91) - * - * (3) In general, an interrupt can be raised before the psns and ssts have - * meaningful values. One should wait for the psns to show the REQ bit (0x80) - * set before expecting meaningful values, with the exception of (2) above. - * Currently this is handled by spc_err_generic ("Late REQ"). (This problem - * is really a refinement of (1)). (danner@cs.cmu.edu 6/14/91) - * - * (4) When issuing a multibyte command after a select with attention, - * The chip will automatically drop ATN before sending the last byte of the - * message, in accordance with the ANSI SCSI standard. This requires, of course, - * the transfer counter be an accurate representation of the amount of data to be - * transfered. (danner@cs.cmu.edu 6/14/91) - * - */ - -#if 0 - -#include <platforms.h> - -#include <scsi.h> - -#if NSCSI > 0 - -#include <mach/std_types.h> -#include <sys/types.h> -#include <chips/busses.h> -#include <scsi/compat_30.h> -#include <sys/syslog.h> -#include <scsi/scsi.h> -#include <scsi/scsi2.h> -#include <scsi/scsi_defs.h> -#include <scsi/adapters/scsi_89352.h> - -#include <machine/db_machdep.h> /*4proto*/ -#include <ddb/db_sym.h> /*4proto*/ - -#ifdef LUNA88K -#include <luna88k/board.h> -#define SPC_DEFAULT_ADDRESS (caddr_t) SCSI_ADDR -#endif - -#ifndef SPC_DEFAULT_ADDRESS /* cross compile check */ -#define SPC_DEFAULT_ADDRESS (caddr_t) 0 -#endif - - -/* external/forward declarations */ -int spc_probe(), spc_slave(), spc_attach(), scsi_go(); -void spc_reset(), spc_attempt_selection(), spc_target_intr(), spc_bus_reset(); -/* - * Statically allocated command & temp buffers - * This way we can attach/detach drives on-fly - */ -#define PER_TGT_BUFF_DATA 256 - -static char spc_buffer[NSCSI * 8 * PER_TGT_BUFF_DATA]; - -/* - * Macros to make certain things a little more readable - */ - -/* - wait for the desired phase to appear, but make sure the REQ bit set in the psns - (otherwise the values tend to float/be garbage. -*/ - -#define SPC_WAIT_PHASE(p) while(((regs->spc_psns & (SPC_BUS_REQ|SCSI_PHASE_MASK))) \ - != (SPC_BUS_REQ|(p))) - -/* - wait until a phase different than p appears in the psns. Since it is only valid - when the REQ bit is set, don't test unless REQ bit is set. So spin until - REQ is high or the phase is not p. -*/ - -#define SPC_WAIT_PHASE_VANISH(p) while(1) { int _psns_ = regs->spc_psns; \ - if ((_psns_ & SPC_BUS_REQ) && (_psns_ & SCSI_PHASE_MASK)!=p) break; } - - - -/* ?? */ -/* #define SPC_ACK(ptr,phase) (ptr)->spc_pctl = (phase) */ - -/* - * A script has a two parts: a pre-condition and an action. - * The first triggers error handling if not satisfied and in - * our case it is formed by the current bus phase and connected - * condition as per bus status bits. The action part is just a - * function pointer, invoked in a standard way. The script - * pointer is advanced only if the action routine returns TRUE. - * See spc_intr() for how and where this is all done. - */ - -typedef struct script { - char condition; /* expected state at interrupt */ - int (*action)(); /* action routine */ -} *script_t; - -#define SCRIPT_MATCH(psns) (SPC_CUR_PHASE((psns))|((psns) & SPC_BUS_BSY)) - -/* ?? */ -#define SPC_PHASE_DISC 0x0 /* sort of .. */ - -/* The active script is in the state expected right after the issue of a select */ - -#define SCRIPT_SELECT(scp) (scp->action == spc_issue_command || \ - scp->action == spc_issue_ident_and_command) - -/* forward decls of script actions */ -boolean_t - spc_dosynch(), /* negotiate synch xfer */ - spc_xfer_in(), /* get data from target via dma */ - spc_xfer_out(), /* send data to target via dma */ - spc_get_status(), /* get status from target */ - spc_end_transaction(), /* all come to an end */ - spc_msg_in(), /* get disconnect message(s) */ - spc_issue_command(), /* spit on the bus */ - spc_issue_ident_and_command(), /* spit on the bus (with ATN) */ - spc_disconnected(); /* current target disconnected */ -/* forward decls of error handlers */ -boolean_t - spc_err_generic(), /* generic error handler */ - spc_err_disconn(); /* when a target disconnects */ -void gimmeabreak(); /* drop into the debugger */ - -void spc_reset_scsibus(); -boolean_t spc_probe_target(); - -scsi_ret_t spc_select_target(); - -/* - * State descriptor for this layer. There is one such structure - * per (enabled) 89352 chip - */ -struct spc_softc { - watchdog_t wd; - spc_regmap_t *regs; /* 5380 registers */ - char *buff; /* scratch buffer memory */ - char *data_ptr; /* orig/dest memory */ - script_t script; - int (*error_handler)(); - int in_count; /* amnt we expect to receive */ - int out_count; /* amnt we are going to ship */ - - volatile char state; -#define SPC_STATE_BUSY 0x01 /* selecting or currently connected */ -#define SPC_STATE_TARGET 0x04 /* currently selected as target */ -#define SPC_STATE_COLLISION 0x08 /* lost selection attempt */ -#define SPC_STATE_DMA_IN 0x10 /* tgt --> initiator xfer */ - - unsigned char ntargets; /* how many alive on this scsibus */ - unsigned char done; - unsigned char xxxx; - - scsi_softc_t *sc; - target_info_t *active_target; - - target_info_t *next_target; /* trying to seize bus */ - queue_head_t waiting_targets;/* other targets competing for bus */ - decl_simple_lock_data(,chiplock) /* Interlock */ -} spc_softc_data[NSCSI]; - -typedef struct spc_softc *spc_softc_t; - -spc_softc_t spc_softc[NSCSI]; - -/* - * Definition of the controller for the auto-configuration program. - */ - -int spc_probe(), scsi_slave(), spc_go(); -void spc_intr(); -void scsi_attach(); - -vm_offset_t spc_std[NSCSI] = { SPC_DEFAULT_ADDRESS }; - -struct bus_device *spc_dinfo[NSCSI*8]; -struct bus_ctlr *spc_minfo[NSCSI]; -struct bus_driver spc_driver = - { spc_probe, scsi_slave, scsi_attach, spc_go, spc_std, "rz", spc_dinfo, - "spc", spc_minfo, BUS_INTR_B4_PROBE}; - -/* - * Scripts - */ - -struct script -spc_script_data_in[] = { - { SCSI_PHASE_CMD|SPC_BUS_BSY, spc_issue_command}, - { SCSI_PHASE_DATAI|SPC_BUS_BSY, spc_xfer_in}, - { SCSI_PHASE_STATUS|SPC_BUS_BSY, spc_get_status}, - { SCSI_PHASE_MSG_IN|SPC_BUS_BSY, spc_end_transaction} -}, - -spc_script_late_data_in[] = { - { SCSI_PHASE_MSG_OUT|SPC_BUS_BSY, spc_issue_ident_and_command}, - { SCSI_PHASE_DATAI|SPC_BUS_BSY, spc_xfer_in}, - { SCSI_PHASE_STATUS|SPC_BUS_BSY, spc_get_status}, - { SCSI_PHASE_MSG_IN|SPC_BUS_BSY, spc_end_transaction} -}, - -spc_script_data_out[] = { - { SCSI_PHASE_CMD|SPC_BUS_BSY, spc_issue_command}, - { SCSI_PHASE_DATAO|SPC_BUS_BSY, spc_xfer_out}, - { SCSI_PHASE_STATUS|SPC_BUS_BSY, spc_get_status}, - { SCSI_PHASE_MSG_IN|SPC_BUS_BSY, spc_end_transaction} -}, - - -spc_script_late_data_out[] = { - { SCSI_PHASE_MSG_OUT|SPC_BUS_BSY, spc_issue_ident_and_command}, - { SCSI_PHASE_DATAO|SPC_BUS_BSY, spc_xfer_out}, - { SCSI_PHASE_STATUS|SPC_BUS_BSY, spc_get_status}, - { SCSI_PHASE_MSG_IN|SPC_BUS_BSY, spc_end_transaction} -}, - - -spc_script_cmd[] = { - { SCSI_PHASE_CMD|SPC_BUS_BSY, spc_issue_command}, - { SCSI_PHASE_STATUS|SPC_BUS_BSY, spc_get_status}, - { SCSI_PHASE_MSG_IN|SPC_BUS_BSY, spc_end_transaction} -}, - -spc_script_late_cmd[] = { - { SCSI_PHASE_MSG_OUT|SPC_BUS_BSY, spc_issue_ident_and_command}, - { SCSI_PHASE_STATUS|SPC_BUS_BSY, spc_get_status}, - { SCSI_PHASE_MSG_IN|SPC_BUS_BSY, spc_end_transaction} -}, - -/* Synchronous transfer neg(oti)ation */ - -spc_script_try_synch[] = { - { SCSI_PHASE_MSG_OUT|SPC_BUS_BSY, spc_dosynch} -}, - -/* Disconnect sequence */ - -spc_script_disconnect[] = { - { SPC_PHASE_DISC, spc_disconnected} -}; - - - -#define u_min(a,b) (((a) < (b)) ? (a) : (b)) - - -#define DEBUG -#ifdef DEBUG - -int spc_state(base) - vm_offset_t base; -{ - register spc_regmap_t *regs; - - if (base == 0) - base = (vm_offset_t) SPC_DEFAULT_ADDRESS; - - regs = (spc_regmap_t*) (base); - - db_printf("spc_bdid (bus device #): %x\n",regs->spc_bdid); - db_printf("spc_sctl (spc internal control): %x\n",regs->spc_sctl); - db_printf("spc_scmd (scp command): %x\n",regs->spc_scmd); - db_printf("spc_ints (spc interrupt): %x\n",regs->spc_ints); - db_printf("spc_psns (scsi bus phase): %x\n",regs->spc_psns); - db_printf("spc_ssts (spc internal status): %x\n",regs->spc_ssts); - db_printf("spc_serr (spc internal err stat): %x\n",regs->spc_serr); - db_printf("spc_pctl (scsi transfer phase): %x\n",regs->spc_pctl); - db_printf("spc_mbc (spc transfer data ct): %x\n",regs->spc_mbc); -/* db_printf("spc_dreg (spc transfer data r/w): %x\n",regs->spc_dreg);*/ - db_printf("spc_temp (scsi data bus control): %x\n",regs->spc_temp); - db_printf("spc_tch (transfer byte ct (MSB): %x\n",regs->spc_tch); - db_printf("spc_tcm (transfer byte ct (2nd): %x\n",regs->spc_tcm); - db_printf("spc_tcl (transfer byte ct (LSB): %x\n",regs->spc_tcl); - - return 0; -} - -int spc_target_state(tgt) - target_info_t *tgt; -{ - if (tgt == 0) - tgt = spc_softc[0]->active_target; - if (tgt == 0) - return 0; - db_printf("fl %x dma %x+%x cmd %x id %x per %x off %x ior %x ret %x\n", - tgt->flags, tgt->dma_ptr, tgt->transient_state.dma_offset, - tgt->cmd_ptr, tgt->target_id, tgt->sync_period, tgt->sync_offset, - tgt->ior, tgt->done); - if (tgt->flags & TGT_DISCONNECTED){ - script_t spt; - - spt = tgt->transient_state.script; - db_printf("disconnected at "); - db_printsym((db_expr_t)spt,1); - db_printf(": %x ", spt->condition); - db_printsym((db_expr_t)spt->action,1); - db_printf(", "); - db_printsym((db_expr_t)tgt->transient_state.handler, 1); - db_printf("\n"); - } - - return 0; -} - -void spc_all_targets(unit) -int unit; -{ - int i; - target_info_t *tgt; - for (i = 0; i < 8; i++) { - tgt = spc_softc[unit]->sc->target[i]; - if (tgt) - spc_target_state(tgt); - } -} - -int spc_script_state(unit) -int unit; -{ - script_t spt = spc_softc[unit]->script; - - if (spt == 0) return 0; - db_printsym((db_expr_t)spt,1); - db_printf(": %x ", spt->condition); - db_printsym((db_expr_t)spt->action,1); - db_printf(", "); - db_printsym((db_expr_t)spc_softc[unit]->error_handler, 1); - return 0; -} - -#define PRINT(x) if (scsi_debug) printf x - -#define TRMAX 200 -int tr[TRMAX+3]; -int trpt, trpthi; -#define TR(x) tr[trpt++] = x -#define TRWRAP trpthi = trpt; trpt = 0; -#define TRCHECK if (trpt > TRMAX) {TRWRAP} - -#define TRACE - -#ifdef TRACE - -#define LOGSIZE 256 -int spc_logpt; -int spc_log[LOGSIZE]; - -#define MAXLOG_VALUE 0x30 -struct { - char *name; - unsigned int count; -} logtbl[MAXLOG_VALUE]; - -static void LOG(e,f) - int e; - char *f; -{ - spc_log[spc_logpt++] = (e); - if (spc_logpt == LOGSIZE) spc_logpt = 0; - if ((e) < MAXLOG_VALUE) { - logtbl[(e)].name = (f); - logtbl[(e)].count++; - } -} - -int spc_print_log(skip) - int skip; -{ - register int i, j; - register unsigned int c; - - for (i = 0, j = spc_logpt; i < LOGSIZE; i++) { - c = spc_log[j]; - if (++j == LOGSIZE) j = 0; - if (skip-- > 0) - continue; - if (c < MAXLOG_VALUE) - db_printf(" %s", logtbl[c].name); - else - db_printf("-0x%x", c - 0x80); - } - db_printf("\n"); - return 0; -} - -void spc_print_stat() -{ - register int i; - register char *p; - for (i = 0; i < MAXLOG_VALUE; i++) { - if (p = logtbl[i].name) - printf("%d %s\n", logtbl[i].count, p); - } -} - -#else /* TRACE */ -#define LOG(e,f) -#endif /* TRACE */ - -#else /* DEBUG */ -#define PRINT(x) -#define LOG(e,f) -#define TR(x) -#define TRCHECK -#define TRWRAP -#endif /* DEBUG */ - - -/* - * Probe/Slave/Attach functions - */ - -/* - * Probe routine: - * Should find out (a) if the controller is - * present and (b) which/where slaves are present. - * - * Implementation: - * Send an identify msg to each possible target on the bus - * except of course ourselves. - */ -int spc_probe(reg, ui) - char *reg; - struct bus_ctlr *ui; -{ - int tmp; - int unit = ui->unit; - spc_softc_t spc = &spc_softc_data[unit]; - int target_id, i; - scsi_softc_t *sc; - register spc_regmap_t *regs; - int s; - boolean_t did_banner = FALSE; - char *cmd_ptr; - - /* - * We are only called if the chip is there, - * but make sure anyways.. - */ - regs = (spc_regmap_t *) (reg); - if (check_memory((unsigned)regs, 0)) - return 0; - -#if notyet - /* Mappable version side */ - SPC_probe(reg, ui); -#endif - - /* - * Initialize hw descriptor - */ - spc_softc[unit] = spc; - spc->regs = regs; - spc->buff = spc_buffer; - - queue_init(&spc->waiting_targets); - - simple_lock_init(&spc->chiplock); - - sc = scsi_master_alloc(unit, (char*)spc); - spc->sc = sc; - - sc->go = spc_go; - sc->probe = spc_probe_target; - sc->watchdog = scsi_watchdog; - spc->wd.reset = spc_reset_scsibus; - -#ifdef MACH_KERNEL - sc->max_dma_data = -1; /* unlimited */ -#else - sc->max_dma_data = scsi_per_target_virtual; -#endif - - scsi_might_disconnect[unit] = 0; /* XXX for now */ - - /* - * Reset chip - */ - s = splbio(); - spc_reset(regs, TRUE); - tmp = regs->spc_ints = regs->spc_ints; - - /* - * Our SCSI id on the bus. - */ - - sc->initiator_id = bdid_to_id(regs->spc_bdid); - printf("%s%d: my SCSI id is %d", ui->name, unit, sc->initiator_id); - - /* - * For all possible targets, see if there is one and allocate - * a descriptor for it if it is there. - */ - cmd_ptr = spc_buffer; - for (target_id = 0; target_id < 8; target_id++, cmd_ptr += PER_TGT_BUFF_DATA) { - - register unsigned csr, ints; - scsi_status_byte_t status; - - /* except of course ourselves */ - if (target_id == sc->initiator_id) - continue; - - if (spc_select_target( regs, sc->initiator_id, target_id, FALSE) - == SCSI_RET_DEVICE_DOWN) { - tmp = regs->spc_ints = regs->spc_ints; - continue; - } - - printf(",%s%d", did_banner++ ? " " : " target(s) at ", - target_id); - - /* should be command phase here: we selected wo ATN! */ - SPC_WAIT_PHASE(SCSI_PHASE_CMD); - - SPC_ACK(regs,SCSI_PHASE_CMD); - - /* build command in buffer */ - { - unsigned char *p = (unsigned char*) cmd_ptr; - - p[0] = SCSI_CMD_TEST_UNIT_READY; - p[1] = - p[2] = - p[3] = - p[4] = - p[5] = 0; - } - - spc_data_out(regs, SCSI_PHASE_CMD, 6, cmd_ptr); - - SPC_WAIT_PHASE(SCSI_PHASE_STATUS); - - /* should have recieved a Command Complete Interrupt */ - while (!(regs->spc_ints)) - delay(1); - ints = regs->spc_ints; - if (ints != (SPC_INTS_DONE)) - gimmeabreak(); - regs->spc_ints = ints; - - SPC_ACK(regs,SCSI_PHASE_STATUS); - - csr = spc_data_in(regs, SCSI_PHASE_STATUS, 1, &status.bits); - LOG(0x25,"din_count"); - LOG(0x80+csr,0); - - if (status.st.scsi_status_code != SCSI_ST_GOOD) - scsi_error( 0, SCSI_ERR_STATUS, status.bits, 0); - - /* expect command complete interupt */ - while (!(regs->spc_ints & SPC_INTS_DONE)) - delay(1); - - /* clear all intr bits */ - tmp = regs->spc_ints; - LOG(0x26,"ints"); - LOG(0x80+tmp,0); - regs->spc_ints = SPC_INTS_DONE; - - /* get cmd_complete message */ - SPC_WAIT_PHASE(SCSI_PHASE_MSG_IN); - - SPC_ACK(regs,SCSI_PHASE_MSG_IN); - - csr = spc_data_in(regs,SCSI_PHASE_MSG_IN, 1,(unsigned char*)&i); - LOG(0x25,"din_count"); - LOG(0x80+csr,0); - - while (!(regs->spc_ints & SPC_INTS_DONE)) - delay(1); - - /* clear all done intr */ - tmp = regs->spc_ints; - LOG(0x26,"ints"); - LOG(0x80+tmp,0); - regs->spc_ints = SPC_INTS_DONE; - - SPC_ACK(regs,SPC_PHASE_DISC); - - /* release the bus */ - regs->spc_pctl = ~SPC_PCTL_BFREE_IE & SPC_PHASE_DISC; - /* regs->spc_scmd = 0; only in TARGET mode */ - - /* wait for disconnected interrupt */ - while (!(regs->spc_ints & SPC_INTS_DISC)) - delay(1); - - tmp = regs->spc_ints; - LOG(0x26,"ints"); - LOG(0x80+tmp,0); - regs->spc_ints = tmp; - LOG(0x29,"Probed\n"); - - /* - * Found a target - */ - spc->ntargets++; - { - register target_info_t *tgt; - - tgt = scsi_slave_alloc(unit, target_id, (char*)spc); - - /* "virtual" address for our use */ - tgt->cmd_ptr = cmd_ptr; - /* "physical" address for dma engine (??) */ - tgt->dma_ptr = 0; -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - fdma_init(&tgt->fdma, scsi_per_target_virtual); -#endif /*MACH_KERNEL*/ - } - } - printf(".\n"); - - splx(s); - return 1; -} - -boolean_t -spc_probe_target(tgt, ior) - target_info_t *tgt; - io_req_t ior; -{ - boolean_t newlywed; - - newlywed = (tgt->cmd_ptr == 0); - if (newlywed) { - /* desc was allocated afresh */ - - /* "virtual" address for our use */ - tgt->cmd_ptr = &spc_buffer[PER_TGT_BUFF_DATA*tgt->target_id + - (tgt->masterno*8*PER_TGT_BUFF_DATA) ]; - /* "physical" address for dma engine */ - tgt->dma_ptr = 0; -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - fdma_init(&tgt->fdma, scsi_per_target_virtual); -#endif /*MACH_KERNEL*/ - - } - - if (scsi_inquiry(tgt, SCSI_INQ_STD_DATA) == SCSI_RET_DEVICE_DOWN) - return FALSE; - - tgt->flags = TGT_ALIVE; - return TRUE; -} - -int bdid_to_id(bdid) - register int bdid; -{ - register int i; - for (i = 0; i < 8; i++) - if (bdid == (1 << i)) break; - return i; -} - -scsi_ret_t -spc_select_target(regs, myid, id, with_atn) - register spc_regmap_t *regs; - unsigned myid, id; - boolean_t with_atn; -{ - scsi_ret_t ret = SCSI_RET_RETRY; - int mask; - - if ((regs->spc_phase & (SPC_BUS_BSY|SPC_BUS_SEL)) -#ifdef MIPS - && (regs->spc_phase & (SPC_BUS_BSY|SPC_BUS_SEL)) - && (regs->spc_phase & (SPC_BUS_BSY|SPC_BUS_SEL)) -#endif - ) - return ret; - - /* setup for for select: - -#if 0 - (1) Toggle the Enable transfer bit (turning on the chips - SCSI bus drivers). -#endif - (2) Enable arbitration, parity, reselect display, but - disable interrupt generation to the CPU (we are polling). - (3) Disable the bus free interrupt and set I/O direction - (4) If doing a select with attention, write the Set attention command. - Then delay 1 microsecond to avoid command races. - - (5) Temp register gets 1<<target | 1<<initiator ids - (6) Timeout clocked into transfer registers - (7) Drive select (and optionally attention) onto the bus - (8) Wait 1/4 second for timeout. - */ - -#if 0 - regs->spc_psns = SPC_DIAG_ENBL_XFER; /* (1) */ -#endif - - regs->spc_sctl = SPC_SCTL_ARB_EBL| - SPC_SCTL_PAR_EBL| - SPC_SCTL_RSEL_EBL; /* (2) */ - - - - mask = ~SPC_PCTL_BFREE_IE & regs->spc_pctl; - mask &= ~1; /* set I/O direction to be out */ - - regs->spc_pctl = mask; /* (3) */ - - if (with_atn) - { - regs->spc_scmd = SPC_SCMD_C_ATN_S; /* (4) */ - delay(1); - } - - regs->spc_temp = (1<<myid) | (1<<id); /* (5) */ - - SPC_TC_PUT(regs,0xfa004); /* (6) */ - - regs->spc_scmd = (SPC_SCMD_C_SELECT | SPC_SCMD_PROGRAMMED_X); /* (7) */ - - { - int count = 2500; - - /* wait for an interrupt */ - while ((regs->spc_ints)==0) - { - if (--count > 0) - delay(100); - else - { - goto nodev; - } - } - - count = regs->spc_ints; - if (count & SPC_INTS_TIMEOUT) - { - /* sanity check. The ssts should have the busy bit set */ - if (regs->spc_ssts & SPC_SSTS_BUSY) - goto nodev; - else - panic("spc_select_target: timeout"); - } - - /* otherwise, we should have received a - command complete interrupt */ - - if (count & ~SPC_INTS_DONE) - panic("spc_select_target"); - - } /* (8) */ - - /* we got a response - now connected; bus is in COMMAND phase */ - - regs->spc_ints = regs->spc_ints; - /* regs->spc_scmd = 0; target only */ - return SCSI_RET_SUCCESS; -nodev: - SPC_TC_PUT(regs,0); /* play it safe */ - regs->spc_ints = regs->spc_ints; - /* regs->spc_scmd = 0; target only */ - ret = SCSI_RET_DEVICE_DOWN; - return ret; -} - -int spc_data_out(regs, phase, count, data) - int phase, count; - register spc_regmap_t *regs; - unsigned char *data; -{ - /* This is the one that sends data out. returns how many - bytes it did NOT xfer: */ - - if (SPC_CUR_PHASE(regs->spc_phase) != phase) - return count; - - /* check that the fifo is empty. If not, cry */ - if (!(regs->spc_ssts & SPC_SSTS_FIFO_EMPTY)) - panic("spc_data_out: junk in fifo\n"); - - SPC_TC_PUT(regs,count); - regs->spc_scmd = SPC_SCMD_C_XFER | SPC_SCMD_PROGRAMMED_X; - - /* wait for the SPC to start processing the command */ - while ((regs->spc_ssts & (SPC_SSTS_INI_CON|SPC_SSTS_TGT_CON|SPC_SSTS_BUSY|SPC_SSTS_XIP)) - != (SPC_SSTS_INI_CON|SPC_SSTS_BUSY|SPC_SSTS_XIP)) - delay(1); - - /* shovel out the data */ - - while (count) - { - /* check if interrupt is pending */ - int ints = regs->spc_ints; - int ssts; - - if (ints) /* something has gone wrong */ - break; - - ssts = regs->spc_ssts; - if (ssts & SPC_SSTS_FIFO_FULL) /* full fifo - can't write */ - delay(1); - else - { /* spit out a byte */ - regs->spc_dreg = *data; - data++; - count--; - } - } - - - if (count != 0) - { - /* need some sort of fifo cleanup if failed */ - gimmeabreak(); /* Bytes stranded in the fifo */ - } - - return count; -} - -int spc_data_in(regs, phase, count, data) - int phase, count; - register spc_regmap_t *regs; - unsigned char *data; -{ - if (SPC_CUR_PHASE(regs->spc_phase) != phase) - return count; - - SPC_TC_PUT(regs,count); - regs->spc_scmd = SPC_SCMD_C_XFER | SPC_SCMD_PROGRAMMED_X; - - /* The Fujistu code sample suggests waiting for the top nibble of the SSTS to - become 0xb (ssts & 0xf0) = 0xb. This state, however is transient. If the - message is short (say , 1 byte), it can get sucked into the fifo before - we ever get to look at the state. So instead, we are going to wait for - the fifo to become nonempty. - */ - - while ((regs->spc_ssts & SPC_SSTS_FIFO_EMPTY)) - delay(1); - - while (count) - { - int ints = regs->spc_ints; - int ssts; - - /* If there is an interrupt pending besides command complete or - phase mismatch, give up */ - - if (ints & ~(SPC_INTS_DONE|SPC_INTS_BUSREQ)) - break; - - /* see if there is any data in the fifo */ - ssts = regs->spc_ssts; - if ((ssts & SPC_SSTS_FIFO_EMPTY) == 0) - { - *data = regs->spc_dreg; - data++; - count--; - continue; - } - - /* if empty, check if phase has changed */ - if (SPC_CUR_PHASE(regs->spc_phase) != phase) - break; - - } - - if ((count==0) && (phase == SCSI_PHASE_MSG_IN)) - { - while (!(regs->spc_ints & SPC_INTS_DONE)) - delay(1); - - /* - So the command complete interrupt has arrived. Now check that the - other two conditions we expect - The psns to be in ack|busy|message_in phase - and ssts to indicate connected|xfer in progress|busy|xfer counter 0|empty fifo - are true. - */ - while (1) - { - register int psns = regs->spc_psns; - register int ssts = regs->spc_ssts; - register int sscon = ssts & (SPC_SSTS_INI_CON | SPC_SSTS_TGT_CON); - register int ssncon = ssts & ~(SPC_SSTS_INI_CON | SPC_SSTS_TGT_CON); - - if (psns == (SPC_BUS_ACK | SPC_BUS_BSY | SCSI_PHASE_MSG_IN) && - ssncon == (SPC_SSTS_BUSY | SPC_SSTS_XIP | SPC_SSTS_TC0 | SPC_SSTS_FIFO_EMPTY) && - sscon) - break; - } - - regs->spc_scmd = SPC_SCMD_C_ACKREQ_C; - } - - return count; -} - -void spc_reset(regs, quickly) - register spc_regmap_t *regs; - boolean_t quickly; -{ - register char myid; - - /* save our id across reset */ - myid = bdid_to_id(regs->spc_bdid); - - /* wait for Reset In signal to go low */ - while (regs->spc_ssts & SPC_SSTS_RST) - delay(1); - - /* reset chip */ - regs->spc_sctl = SPC_SCTL_RESET; - delay(25); - - regs->spc_myid = myid; - regs->spc_sctl = SPC_SCTL_ARB_EBL|SPC_SCTL_PAR_EBL|SPC_SCTL_SEL_EBL| - SPC_SCTL_RSEL_EBL|SPC_SCTL_IE; - regs->spc_scmd = SPC_SCMD_C_BUS_RLSE; - /* regs->spc_tmod = 0; - SANDRO ? */ - regs->spc_ints = 0xff;/* clear off any pending */ -#if 0 - regs->spc_pctl = SPC_PCTL_LST_IE; /* useful only on 87033 */ -#else - regs->spc_pctl = 0; -#endif - regs->spc_mbc = 0; - SPC_TC_PUT(regs,0); - - if (quickly) - return; - - /* - * reset the scsi bus, the interrupt routine does the rest - * or you can call spc_bus_reset(). - */ - regs->spc_scmd = SPC_SCMD_BUSRST|SPC_SCMD_C_STOP_X;/*?*/ -} - -/* - * Operational functions - */ - -/* - * Start a SCSI command on a target - */ -spc_go(tgt, cmd_count, in_count, cmd_only) - int cmd_count, in_count; - target_info_t *tgt; - boolean_t cmd_only; -{ - spc_softc_t spc; - register int s; - boolean_t disconn; - script_t scp; - boolean_t (*handler)(); - int late; - - LOG(1,"\n\tgo"); - - spc = (spc_softc_t)tgt->hw_state; - - /* - * We cannot do real DMA. - */ -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - if (tgt->ior) - fdma_map(&tgt->fdma, tgt->ior); -#endif /*MACH_KERNEL*/ - - if ((tgt->cur_cmd == SCSI_CMD_WRITE) || - (tgt->cur_cmd == SCSI_CMD_LONG_WRITE)){ - io_req_t ior = tgt->ior; - register int len = ior->io_count; - - tgt->transient_state.out_count = len; - tgt->transient_state.copy_count = 0; - - if (len < tgt->block_size) { - gimmeabreak(); - - /* avoid leaks */ -#if 0 -you`ll have to special case this -#endif - tgt->transient_state.out_count = tgt->block_size; - } - } else { - tgt->transient_state.out_count = 0; - tgt->transient_state.copy_count = 0; - } - - tgt->transient_state.cmd_count = cmd_count; - - disconn = - BGET(scsi_might_disconnect,(unsigned)tgt->masterno, tgt->target_id); - disconn = disconn && (spc->ntargets > 1); - disconn |= - BGET(scsi_should_disconnect,(unsigned)tgt->masterno, tgt->target_id); - - /* - * Setup target state - */ - tgt->done = SCSI_RET_IN_PROGRESS; - - handler = (disconn) ? spc_err_disconn : spc_err_generic; - - /* determine wether or not to use the late forms of the scripts */ - late = cmd_only ? FALSE : (tgt->flags & TGT_DID_SYNCH); - - switch (tgt->cur_cmd) { - case SCSI_CMD_READ: - case SCSI_CMD_LONG_READ: - LOG(0x13,"readop"); - scp = late ? spc_script_late_data_in : spc_script_data_in; - break; - case SCSI_CMD_WRITE: - case SCSI_CMD_LONG_WRITE: - LOG(0x14,"writeop"); - scp = late ? spc_script_late_data_out : spc_script_data_out; - break; - case SCSI_CMD_INQUIRY: - /* This is likely the first thing out: - do the synch neg if so */ - if (!cmd_only && ((tgt->flags&TGT_DID_SYNCH)==0)) { - scp = spc_script_try_synch; - tgt->flags |= TGT_TRY_SYNCH; - break; - } - case SCSI_CMD_REQUEST_SENSE: - case SCSI_CMD_MODE_SENSE: - case SCSI_CMD_RECEIVE_DIAG_RESULTS: - case SCSI_CMD_READ_CAPACITY: - case SCSI_CMD_READ_BLOCK_LIMITS: - case SCSI_CMD_READ_TOC: - case SCSI_CMD_READ_SUBCH: - case SCSI_CMD_READ_HEADER: - case 0xc4: /* despised: SCSI_CMD_DEC_PLAYBACK_STATUS */ - case 0xc6: /* despised: SCSI_CMD_TOSHIBA_READ_SUBCH_Q */ - case 0xc7: /* despised: SCSI_CMD_TOSHIBA_READ_TOC_ENTRY */ - case 0xdd: /* despised: SCSI_CMD_NEC_READ_SUBCH_Q */ - case 0xde: /* despised: SCSI_CMD_NEC_READ_TOC */ - scp = late ? spc_script_late_data_in : spc_script_data_in; - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - case SCSI_CMD_MODE_SELECT: - case SCSI_CMD_REASSIGN_BLOCKS: - case SCSI_CMD_FORMAT_UNIT: - case 0xc9: /* vendor-spec: SCSI_CMD_DEC_PLAYBACK_CONTROL */ - tgt->transient_state.cmd_count = sizeof_scsi_command(tgt->cur_cmd); - tgt->transient_state.out_count = - cmd_count - tgt->transient_state.cmd_count; - scp = late ? spc_script_late_data_out : spc_script_data_out; - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - case SCSI_CMD_TEST_UNIT_READY: - /* - * Do the synch negotiation here, unless prohibited - * or done already - */ - if (tgt->flags & TGT_DID_SYNCH) { - scp = late ? spc_script_late_cmd : spc_script_cmd; - } else { - scp = spc_script_try_synch; - tgt->flags |= TGT_TRY_SYNCH; - cmd_only = FALSE; - } - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - default: - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - scp = late ? spc_script_late_cmd : spc_script_cmd; - } - - tgt->transient_state.script = scp; - tgt->transient_state.handler = handler; - tgt->transient_state.identify = (cmd_only) ? 0xff : - (disconn ? SCSI_IDENTIFY|SCSI_IFY_ENABLE_DISCONNECT : - SCSI_IDENTIFY); - - if (in_count) - tgt->transient_state.in_count = - (in_count < tgt->block_size) ? tgt->block_size : in_count; - else - tgt->transient_state.in_count = 0; - tgt->transient_state.dma_offset = 0; - - /* - * See if another target is currently selected on - * this SCSI bus, e.g. lock the spc structure. - * Note that it is the strategy routine's job - * to serialize ops on the same target as appropriate. - */ -#if 0 -locking code here -#endif - s = splbio(); - - if (spc->wd.nactive++ == 0) - spc->wd.watchdog_state = SCSI_WD_ACTIVE; - - if (spc->state & SPC_STATE_BUSY) { - /* - * Queue up this target, note that this takes care - * of proper FIFO scheduling of the scsi-bus. - */ - LOG(3,"enqueue"); - enqueue_tail(&spc->waiting_targets, (queue_entry_t) tgt); - } else { - /* - * It is down to at most two contenders now, - * we will treat reconnections same as selections - * and let the scsi-bus arbitration process decide. - */ - spc->state |= SPC_STATE_BUSY; - spc->next_target = tgt; - spc_attempt_selection(spc); - /* - * Note that we might still lose arbitration.. - */ - } - splx(s); -} - -void spc_attempt_selection(spc) - spc_softc_t spc; -{ - target_info_t *tgt; - spc_regmap_t *regs; - register int cmd; - int atn=0; - - /* This is about your select code */ - - regs = spc->regs; - tgt = spc->next_target; - - LOG(4,"select"); - LOG(0x80+tgt->target_id,0); - - /* - * Init bus state variables and set registers. - */ - spc->active_target = tgt; - - /* reselection pending ? */ - if ((regs->spc_phase & (SPC_BUS_BSY|SPC_BUS_SEL)) -#ifdef MIPS - && (regs->spc_phase & (SPC_BUS_BSY|SPC_BUS_SEL)) - && (regs->spc_phase & (SPC_BUS_BSY|SPC_BUS_SEL)) -#endif - ) - return; - - spc->script = tgt->transient_state.script; - spc->error_handler = tgt->transient_state.handler; - spc->done = SCSI_RET_IN_PROGRESS; - - spc->in_count = 0; - spc->out_count = 0; - - cmd = SPC_SCMD_C_SELECT | SPC_SCMD_PROGRAMMED_X; - if (tgt->flags & TGT_DID_SYNCH) - { - if (tgt->transient_state.identify != 0xff) - atn = 1; - } - else - if (tgt->flags & TGT_TRY_SYNCH) - atn = 1; - -#if 0 - regs->spc_psns = SPC_DIAG_ENBL_XFER; -#endif - - regs->spc_sctl = SPC_SCTL_ARB_EBL | SPC_SCTL_PAR_EBL | - SPC_SCTL_RSEL_EBL | SPC_SCTL_IE; - - - { int mask; - mask = ~SPC_PCTL_BFREE_IE & regs->spc_pctl; - regs->spc_pctl = mask; - } - - regs->spc_temp = (1<<(spc->sc->initiator_id)) | (1<<(tgt->target_id)); - - SPC_TC_PUT(regs,0xfa004); - - if (atn) - { - regs->spc_scmd = SPC_SCMD_C_ATN_S; - /* delay 1us to avoid races */ - delay(1); - } - - regs->spc_scmd = cmd; - return; -} - -/* - * Interrupt routine - * Take interrupts from the chip - * - * Implementation: - * Move along the current command's script if - * all is well, invoke error handler if not. - */ -void spc_intr(unit) -int unit; -{ - register spc_softc_t spc; - register script_t scp; - register unsigned ints, psns, ssts; - register spc_regmap_t *regs; - boolean_t try_match; -#if notyet - extern boolean_t rz_use_mapped_interface; - - if (rz_use_mapped_interface) - { - SPC_intr(unit); - return; - } -#endif - - spc = spc_softc[unit]; - regs = spc->regs; - - /* read the interrupt status register */ - ints = regs->spc_ints; - - LOG(5,"\n\tintr"); - LOG(0x80+ints,0); - -TR(ints); -TRCHECK; - - if (ints & SPC_INTS_RESET) - { - /* does its own interrupt reset when ready */ - spc_bus_reset(spc); - return; - } - - /* we got an interrupt allright */ - if (spc->active_target) - spc->wd.watchdog_state = SCSI_WD_ACTIVE; - - - if (ints == 0) - { /* no obvious cause */ - LOG(2,"SPURIOUS"); - gimmeabreak(); - return; - } - - - /* reset the interrupt */ - regs->spc_ints = ints; - - /* go get the phase, and status. We can't trust the - phase until REQ is asserted in the psns. Only do - this is we received a command complete or service - required interrupt. Otherwise, just read them once - and trust. */ - - - - if (ints & (SPC_INTS_DONE|SPC_INTS_BUSREQ)) - while(1) - { - psns = regs->spc_psns; - if (psns & SPC_BUS_REQ) - break; - delay(1); /* don't hog the bus */ - } - else - psns = regs->spc_psns; - - ssts = regs->spc_psns; - -TR(psns); -TR(ssts); -TRCHECK; - - if ((spc->state & SPC_STATE_TARGET) || - (ints & SPC_INTS_SELECTED)) - spc_target_intr(spc /**, ints, psns, ssts **/); - - scp = spc->script; - - if ((scp == 0) || (ints & SPC_INTS_RESELECTED)) - { - gimmeabreak(); - spc_reconnect(spc, ints, psns, ssts); - return; - } - - if (SCRIPT_MATCH(psns) != scp->condition) { - if (try_match = (*spc->error_handler)(spc, ints, psns, ssts)) { - psns = regs->spc_psns; - ssts = regs->spc_ssts; - } - } else - try_match = TRUE; - - - /* might have been side effected */ - scp = spc->script; - - if (try_match && (SCRIPT_MATCH(psns) == scp->condition)) { - /* - * Perform the appropriate operation, - * then proceed - */ - if ((*scp->action)(spc, ints, psns, ssts)) { - /* might have been side effected */ - scp = spc->script; - spc->script = scp + 1; - } - } -} - -void spc_target_intr(spc) - register spc_softc_t spc; -{ - panic("SPC: TARGET MODE !!!\n"); -} - -/* - * All the many little things that the interrupt - * routine might switch to - */ -boolean_t -spc_issue_command(spc, ints, psns, ssts) - spc_softc_t spc; - int ints, psns, ssts; -{ - register spc_regmap_t *regs = spc->regs; - - LOG(0x12, "cmd_issue"); - /* we have just done a select; - Bus is in CMD phase; - need to phase match */ - SPC_ACK(regs, SCSI_PHASE_CMD); - - return spc_data_out(regs, SCSI_PHASE_CMD, - spc->active_target->transient_state.cmd_count, - spc->active_target->cmd_ptr) ? FALSE : TRUE; -} - -boolean_t -spc_issue_ident_and_command(spc, ints, psns, ssts) - spc_softc_t spc; - int ints, psns, ssts; -{ - register spc_regmap_t *regs = spc->regs; - - LOG(0x22, "ident_and_cmd"); - /* we have just done a select with atn Bus is in MSG_OUT phase; - need to phase match */ - SPC_ACK(regs, SCSI_PHASE_MSG_OUT); - - spc_data_out(regs, SCSI_PHASE_MSG_OUT, 1, - &spc->active_target->transient_state.identify); - - /* wait to go to command phase */ - SPC_WAIT_PHASE(SCSI_PHASE_CMD); - - /* ack */ - SPC_ACK(regs, SCSI_PHASE_CMD); - - /* should be a command complete intr pending. Eat it */ - if (regs->spc_ints != SPC_INTS_DONE) - gimmeabreak(); - regs->spc_ints = SPC_INTS_DONE; - - /* spit */ - return spc_data_out(regs, SCSI_PHASE_CMD, - spc->active_target->transient_state.cmd_count, - spc->active_target->cmd_ptr) ? FALSE : TRUE; -} - - -boolean_t -spc_end_transaction( spc, ints, psns, serr) - register spc_softc_t spc; - int ints, psns, serr; -{ - register spc_regmap_t *regs = spc->regs; - char cmc; - int tmp; - - LOG(0x1f,"end_t"); - - SPC_ACK(regs,SCSI_PHASE_MSG_IN /*,1*/); - - spc_data_in(regs, SCSI_PHASE_MSG_IN, 1, &cmc); - - if (cmc != SCSI_COMMAND_COMPLETE) - printf("{T%x}", cmc); - - while (regs->spc_ints != (SPC_INTS_DONE|SPC_INTS_DISC)); - - SPC_ACK(regs,SPC_PHASE_DISC); - - /* going to disconnect */ - regs->spc_pctl = ~SPC_PCTL_BFREE_IE & SPC_PHASE_DISC; - /* regs->spc_scmd = 0; */ - - /* clear all intr bits? */ - tmp = regs->spc_ints; - regs->spc_ints = tmp; - - - if (!spc_end(spc, ints, psns, serr)) - (void) spc_reconnect(spc, ints, psns, serr); - return FALSE; -} - -boolean_t -spc_end( spc, ints, psns, serr) - register spc_softc_t spc; - int ints, psns, serr; -{ - register target_info_t *tgt; - register io_req_t ior; - register spc_regmap_t *regs = spc->regs; - int csr; - - LOG(6,"end"); - - tgt = spc->active_target; - - if ((tgt->done = spc->done) == SCSI_RET_IN_PROGRESS) - tgt->done = SCSI_RET_SUCCESS; - - spc->script = 0; - - if (spc->wd.nactive-- == 1) - spc->wd.watchdog_state = SCSI_WD_INACTIVE; - - /* check reconnection not pending */ - csr = SPC_INTS_RESELECTED & regs->spc_ints; - if (!csr) - spc_release_bus(spc); - else - { - spc->active_target = 0; - /* spc->state &= ~SPC_STATE_BUSY; later */ - } - if (ior = tgt->ior) { -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - fdma_unmap(&tgt->fdma, ior); -#endif /*MACH_KERNEL*/ - LOG(0xA,"ops->restart"); - (*tgt->dev_ops->restart)( tgt, TRUE); - if (csr) - spc->state &= ~SPC_STATE_BUSY; - } - - /* return not reselected */ - return (csr & SPC_INTS_RESELECTED) ? 0 : 1; -} - -boolean_t -spc_release_bus(spc) - register spc_softc_t spc; -{ - boolean_t ret = FALSE; - - LOG(9,"release"); - - spc->script = 0; - - if (spc->state & SPC_STATE_COLLISION) { - - LOG(0xB,"collided"); - spc->state &= ~SPC_STATE_COLLISION; - spc_attempt_selection(spc); - - } else if (queue_empty(&spc->waiting_targets)) { - - spc->state &= ~SPC_STATE_BUSY; - spc->active_target = 0; - ret = TRUE; - - } else { - - LOG(0xC,"dequeue"); - spc->next_target = (target_info_t *) - dequeue_head(&spc->waiting_targets); - spc_attempt_selection(spc); - } - return ret; -} - -boolean_t -spc_get_status( spc, ints, psns, serr) - register spc_softc_t spc; - int ints, psns, serr; -{ - register spc_regmap_t *regs = spc->regs; - scsi2_status_byte_t status; - register target_info_t *tgt; - - LOG(0xD,"get_status"); -TRWRAP; - - spc->state &= ~SPC_STATE_DMA_IN; - - tgt = spc->active_target; - - SPC_ACK(regs,SCSI_PHASE_STATUS /*,1*/); - - spc_data_in(regs, SCSI_PHASE_STATUS, 1, &status.bits); - - if (status.st.scsi_status_code != SCSI_ST_GOOD) { - scsi_error(spc->active_target, SCSI_ERR_STATUS, status.bits, 0); - spc->done = (status.st.scsi_status_code == SCSI_ST_BUSY) ? - SCSI_RET_RETRY : SCSI_RET_NEED_SENSE; - } else - spc->done = SCSI_RET_SUCCESS; - - return TRUE; -} - -boolean_t -spc_xfer_in( spc, ints, psns, ssts) - register spc_softc_t spc; - int ints, psns, ssts; -{ - register target_info_t *tgt; - register spc_regmap_t *regs = spc->regs; - register int count; - boolean_t advance_script = TRUE; - - LOG(0xE,"xfer_in"); - - tgt = spc->active_target; - spc->state |= SPC_STATE_DMA_IN; - - count = tgt->transient_state.in_count; - - SPC_ACK(regs, SCSI_PHASE_DATAI); - - if ((tgt->cur_cmd != SCSI_CMD_READ) && - (tgt->cur_cmd != SCSI_CMD_LONG_READ)) - spc_data_in(regs, SCSI_PHASE_DATAI, count, tgt->cmd_ptr); - else - { - spc_data_in(regs, SCSI_PHASE_DATAI, count, tgt->ior->io_data); - } - - return advance_script; -} - -boolean_t -spc_xfer_out( spc, ints, psns, ssts) - register spc_softc_t spc; - int ints, psns, ssts; -{ - register spc_regmap_t *regs = spc->regs; - register target_info_t *tgt; - boolean_t advance_script = TRUE; - int count = spc->out_count; - - LOG(0xF,"xfer_out"); - - tgt = spc->active_target; - spc->state &= ~SPC_STATE_DMA_IN; - - count = tgt->transient_state.out_count; - - SPC_ACK(regs, SCSI_PHASE_DATAO); - - if ((tgt->cur_cmd != SCSI_CMD_WRITE) && - (tgt->cur_cmd != SCSI_CMD_LONG_WRITE)) - spc_data_out(regs, SCSI_PHASE_DATAO, count, - tgt->cmd_ptr + tgt->transient_state.cmd_count); - else - spc_data_out(regs, SCSI_PHASE_DATAO, count, tgt->ior->io_data); - - return advance_script; -} - -/* disconnect-reconnect ops */ - -/* get the message in via dma ?? */ -boolean_t -spc_msg_in(spc, ints, psns, ssts) - register spc_softc_t spc; - int ints, psns, ssts; -{ - register target_info_t *tgt; - - LOG(0x15,"msg_in"); - gimmeabreak(); - - tgt = spc->active_target; - -#if 0 -You can do this by hand, just leave an interrupt pending at the end -#endif - - /* We only really expect two bytes */ -#if 0 - SPC_PUT(dmar,sizeof(scsi_command_group_0)); - .... -#endif - return TRUE; -} - -/* check the message is indeed a DISCONNECT */ -boolean_t -spc_disconnect(spc, ints, psns, ssts) - register spc_softc_t spc; - int ints, psns, ssts; -{ - register int len = 0; - boolean_t ok = FALSE; - register char *msgs = 0; - - -/* SPC_TC_GET(dmar,len); */ - len = sizeof(scsi_command_group_0) - len; - -/* msgs = tgt->cmd_ptr; */ /* I think */ - - if ((len == 0) || (len > 2) || msgs == 0) - ok = FALSE; - else { - /* A SDP message preceeds it in non-completed READs */ - ok = ((msgs[0] == SCSI_DISCONNECT) || /* completed op */ - ((msgs[0] == SCSI_SAVE_DATA_POINTER) && /* incomplete */ - (msgs[1] == SCSI_DISCONNECT))); - } - if (!ok) - printf("[tgt %d bad msg (%d): %x]", - spc->active_target->target_id, len, *msgs); - - return TRUE; -} - -/* save all relevant data, free the BUS */ -boolean_t -spc_disconnected(spc, ints, psns, ssts) - register spc_softc_t spc; - int ints, psns, ssts; -{ - register target_info_t *tgt; - -/* make sure reselects will work */ - - LOG(0x16,"disconnected"); - - spc_disconnect(spc,ints, psns, ssts); - - tgt = spc->active_target; - tgt->flags |= TGT_DISCONNECTED; - tgt->transient_state.handler = spc->error_handler; - /* the rest has been saved in spc_err_disconn() */ - - PRINT(("{D%d}", tgt->target_id)); - - spc_release_bus(spc); - - return FALSE; -} - -/* get reconnect message, restore BUS */ -boolean_t -spc_reconnect(spc, ints, psns, ssts) - register spc_softc_t spc; - int ints, psns, ssts; -{ - - LOG(0x17,"reconnect"); - - if (spc->wd.nactive == 0) { - LOG(2,"SPURIOUS"); - return FALSE; - } - -#if 0 -This is the 5380 code, for reference: - spc_regmap_t *regs = spc->regs; - register target_info_t *tgt; - register int id; - int msg; - - - id = regs->spc_data;/*parity?*/ - /* xxx check our id is in there */ - - id &= ~(1 << spc->sc->initiator_id); - { - register int i; - for (i = 0; i < 8; i++) - if (id & (1 << i)) break; -if (i == 8) {printf("{P%x}", id);return;} - id = i; - } - regs->spc_icmd = SPC_ICMD_BSY; - while (regs->spc_bus_csr & SPC_BUS_SEL) - ; - regs->spc_icmd = 0; - delay_1p2_us(); - while ( ((regs->spc_bus_csr & SPC_BUS_BSY) == 0) && - ((regs->spc_bus_csr & SPC_BUS_BSY) == 0) && - ((regs->spc_bus_csr & SPC_BUS_BSY) == 0)) - ; - - /* Now should wait for correct phase: REQ signals it */ - while ( ((regs->spc_bus_csr & SPC_BUS_REQ) == 0) && - ((regs->spc_bus_csr & SPC_BUS_REQ) == 0) && - ((regs->spc_bus_csr & SPC_BUS_REQ) == 0)) - ; - - regs->spc_mode |= SPC_MODE_MONBSY; - - /* - * See if this reconnection collided with a selection attempt - */ - if (spc->state & SPC_STATE_BUSY) - spc->state |= SPC_STATE_COLLISION; - - spc->state |= SPC_STATE_BUSY; - - /* Get identify msg */ - bs = regs->spc_phase; -if (SPC_CUR_PHASE(bs) != SCSI_PHASE_MSG_IN) gimmeabreak(); - SPC_ACK(regs,SCSI_PHASE_MSG_IN /*,1*/); - msg = 0; - spc_data_in(regs, SCSI_PHASE_MSG_IN, 1, &msg); - regs->spc_mode = SPC_MODE_PAR_CHK|SPC_MODE_DMA|SPC_MODE_MONBSY; - - if (msg != SCSI_IDENTIFY) - printf("{I%x %x}", id, msg); - - tgt = spc->sc->target[id]; - if (id > 7 || tgt == 0) panic("spc_reconnect"); - - PRINT(("{R%d}", id)); - if (spc->state & SPC_STATE_COLLISION) - PRINT(("[B %d-%d]", spc->active_target->target_id, id)); - - LOG(0x80+id,0); - - spc->active_target = tgt; - tgt->flags &= ~TGT_DISCONNECTED; - - spc->script = tgt->transient_state.script; - spc->error_handler = tgt->transient_state.handler; - spc->in_count = 0; - spc->out_count = 0; - - /* Should get a phase mismatch when tgt changes phase */ -#endif - return TRUE; -} - - - -/* do the synch negotiation */ -boolean_t -spc_dosynch( spc, ints, psns, ssts) - register spc_softc_t spc; - int ints, psns, ssts; -{ - /* - * Phase is MSG_OUT here, cmd has not been xferred - */ - int len; - register target_info_t *tgt; - register spc_regmap_t *regs = spc->regs; - unsigned char off; - unsigned char p[6]; - - LOG(0x11,"dosync"); - - /* ATN still asserted */ - SPC_ACK(regs,SCSI_PHASE_MSG_OUT); - - tgt = spc->active_target; - - tgt->flags |= TGT_DID_SYNCH; /* only one chance */ - tgt->flags &= ~TGT_TRY_SYNCH; - - /*p = some scratch buffer, on the stack */ - - p[0] = SCSI_IDENTIFY; - p[1] = SCSI_EXTENDED_MESSAGE; - p[2] = 3; - p[3] = SCSI_SYNC_XFER_REQUEST; - /* We cannot run synchronous */ -#define spc_to_scsi_period(x) 0x7 -#define scsi_period_to_spc(x) (x) - off = 0; - p[4] = spc_to_scsi_period(spc_min_period); - p[5] = off; - - /* The transfer is started with ATN still set. The - chip will automagically drop ATN before it transfers the - last byte. Pretty neat. */ - spc_data_out(regs, SCSI_PHASE_MSG_OUT, - sizeof(scsi_synch_xfer_req_t)+1, p); - - /* wait for phase change to status phase */ - SPC_WAIT_PHASE_VANISH(SCSI_PHASE_MSG_OUT); - - - psns = regs->spc_phase; - - /* The standard sez there nothing else the target can do but.. */ - if (SPC_CUR_PHASE(psns) != SCSI_PHASE_MSG_IN) - panic("spc_dosync");/* XXX put offline */ - - /* - msgin: - */ - /* ack */ - SPC_ACK(regs,SCSI_PHASE_MSG_IN); - - /* clear any pending interrupts */ - regs->spc_ints = regs->spc_ints; - - /* get answer */ - len = sizeof(scsi_synch_xfer_req_t); - len = spc_data_in(regs, SCSI_PHASE_MSG_IN, len, p); - - /* do not cancel the phase mismatch interrupt ! */ - - /* look at the answer and see if we like it */ - if (len || (p[0] != SCSI_EXTENDED_MESSAGE)) { - /* did not like it at all */ - printf(" did not like SYNCH xfer "); - } else { - /* will NOT do synch */ - printf(" but we cannot do SYNCH xfer "); - tgt->sync_period = scsi_period_to_spc(p[3]); - tgt->sync_offset = p[4]; - /* sanity */ - if (tgt->sync_offset != 0) - printf(" ?OFFSET %x? ", tgt->sync_offset); - } - - /* wait for phase change */ - SPC_WAIT_PHASE_VANISH(SCSI_PHASE_MSG_IN); - - psns = regs->spc_phase; - - /* phase should be command now */ - /* continue with simple command script */ - spc->error_handler = spc_err_generic; - spc->script = spc_script_cmd; - -/* Make sure you get out right here, esp the script pointer and/or pending intr */ - - if (SPC_CUR_PHASE(psns) == SCSI_PHASE_CMD ) - return FALSE; - - if (SPC_CUR_PHASE(psns) == SCSI_PHASE_STATUS ) /* jump to get_status */ - return TRUE; /* intr is pending */ - - spc->script++; - if (SPC_CUR_PHASE(psns) == SCSI_PHASE_MSG_IN ) - return TRUE; - - if ((psns & SPC_BUS_BSY) == 0) /* uhu? disconnected */ - return TRUE; - - gimmeabreak(); - return FALSE; -} - -/* - * The bus was reset - */ -void spc_bus_reset(spc) - register spc_softc_t spc; -{ - register spc_regmap_t *regs = spc->regs; - - LOG(0x21,"bus_reset"); - - /* - * Clear bus descriptor - */ - spc->script = 0; - spc->error_handler = 0; - spc->active_target = 0; - spc->next_target = 0; - spc->state = 0; - queue_init(&spc->waiting_targets); - spc->wd.nactive = 0; - spc_reset(regs, TRUE); - - printf("spc%d: (%d) bus reset ", spc->sc->masterno, ++spc->wd.reset_count); - delay(scsi_delay_after_reset); /* some targets take long to reset */ - - if (spc->sc == 0) /* sanity */ - return; - - scsi_bus_was_reset(spc->sc); -} - -/* - * Error handlers - */ - -/* - * Generic, default handler - */ -boolean_t -spc_err_generic(spc, ints, psns, ssts) - register spc_softc_t spc; - int ints, psns, ssts; -{ - register spc_regmap_t *regs = spc->regs; - LOG(0x10,"err_generic"); - - if (ints & SPC_INTS_TIMEOUT) /* we timed out */ - if ((regs->spc_scmd & SPC_SCMD_CMDMASK) == SPC_SCMD_C_SELECT) - { - /* Powered off ? */ - if (spc->active_target->flags & TGT_FULLY_PROBED) - { - spc->active_target->flags = 0; - LOG(0x1e,"Device Down"); - } - spc->done = SCSI_RET_DEVICE_DOWN; - spc_end(spc, ints, psns, ssts); - return FALSE; /* don't retry - just report missing device */ - } - else - { /* timed out - but not on a select. What is going on? */ - gimmeabreak(); - } - - if (SPC_CUR_PHASE(psns) == SCSI_PHASE_STATUS) - return spc_err_to_status(spc, ints, psns, ssts); - gimmeabreak(); - return FALSE; -} - -/* - * Handle generic errors that are reported as - * an unexpected change to STATUS phase - */ -boolean_t -spc_err_to_status(spc, ints, psns, ssts) - register spc_softc_t spc; - int ints, psns, ssts; -{ - script_t scp = spc->script; - - LOG(0x20,"err_tostatus"); - while (SCSI_PHASE(scp->condition) != SCSI_PHASE_STATUS) - scp++; - spc->script = scp; -#if 0 - /* - * Normally, we would already be able to say the command - * is in error, e.g. the tape had a filemark or something. - * But in case we do disconnected mode WRITEs, it is quite - * common that the following happens: - * dma_out -> disconnect -> reconnect - * and our script might expect at this point that the dma - * had to be restarted (it didn't know it was completed - * because the tape record is shorter than we asked for). - * And in any event.. it is both correct and cleaner to - * declare error iff the STATUS byte says so. - */ - spc->done = SCSI_RET_NEED_SENSE; -#endif - return TRUE; -} - -/* - * Watch for a disconnection - */ -boolean_t -spc_err_disconn(spc, ints, psns, ssts) - register spc_softc_t spc; - int ints, psns, ssts; -{ -#if 1 -/* - * THIS ROUTINE CAN'T POSSIBLY WORK... - * FOR EXAMPLE, THE VARIABLE 'xferred' IS NEVER INITIALIZED. - */ - return FALSE; -#else - register spc_regmap_t *regs; - register target_info_t *tgt; - int xferred; - - LOG(0x18,"err_disconn"); - - if (SPC_CUR_PHASE(ints) != SCSI_PHASE_MSG_IN) - return spc_err_generic(spc, ints, psns, ssts); - - regs = spc->regs; - - tgt = spc->active_target; - - switch (SCSI_PHASE(spc->script->condition)) { - case SCSI_PHASE_DATAO: - LOG(0x1b,"+DATAO"); -/*updatecounters:*/ - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - tgt->transient_state.dma_offset += xferred; - - tgt->transient_state.script = spc_script_data_out; - break; - - case SCSI_PHASE_DATAI: - LOG(0x19,"+DATAI"); - -/*update counters: */ - assert(xferred > 0); - tgt->transient_state.in_count -= xferred; - assert(tgt->transient_state.in_count > 0); - tgt->transient_state.dma_offset += xferred; - - tgt->transient_state.script = spc_script_data_in; - break; - - case SCSI_PHASE_STATUS: - - if (spc->state & SPC_STATE_DMA_IN) { - - LOG(0x1a,"+STATUS+R"); - -/*same as above.. */ - assert(xferred > 0); - tgt->transient_state.in_count -= xferred; -/* assert(tgt->transient_state.in_count > 0);*/ - tgt->transient_state.dma_offset += xferred; - - tgt->transient_state.script = spc_script_data_in; - if (tgt->transient_state.in_count == 0) - tgt->transient_state.script++; - - } else { - - LOG(0x1d,"+STATUS+W"); - - if ((tgt->transient_state.out_count == spc->out_count)) { - /* all done */ - tgt->transient_state.script = &spc_script_data_out[1]; - tgt->transient_state.out_count = 0; - } else { - -/*.. */ - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - tgt->transient_state.dma_offset += xferred; - - tgt->transient_state.script = spc_script_data_out; - } - spc->out_count = 0; - } - break; - default: - gimmeabreak(); - } - /* spc->xxx = 0; */ - -/* SPC_ACK(regs,SCSI_PHASE_MSG_IN); later */ - (void) spc_msg_in(spc, ints, psns, ssts); - - spc->script = spc_script_disconnect; - - return FALSE; -#endif -} - -/* - * Watchdog - * - */ -void spc_reset_scsibus(spc) - register spc_softc_t spc; -{ - register target_info_t *tgt = spc->active_target; - if (tgt) { - int cnt = 0; - /* SPC_TC_GET(spc->dmar,cnt); */ - log( LOG_KERN, - "Target %d was active, cmd x%x in x%x out x%x Sin x%x Sou x%x dmalen x%x\n", - tgt->target_id, tgt->cur_cmd, - tgt->transient_state.in_count, tgt->transient_state.out_count, - spc->in_count, spc->out_count, cnt); - } -#if 0 - spc->regs->..... -#endif - delay(25); -} - -int SPC_ACK(regs, phase) -register spc_regmap_t *regs; -unsigned phase; -{ - /* we want to switch into the specified phase - - - The calling routine should already dismissed - any pending interrupts (spc_ints) - */ - - regs->spc_psns = 0; - regs->spc_pctl = phase | SPC_PCTL_BFREE_IE; - return 0; -} -#endif /*NSCSI > 0*/ - -#endif 0 diff --git a/scsi/adapters/scsi_aha15.h b/scsi/adapters/scsi_aha15.h deleted file mode 100644 index 52cd936..0000000 --- a/scsi/adapters/scsi_aha15.h +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_aha15.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 6/91 - * - * Definitions for the Adaptec AHA-15xx family - * of Intelligent SCSI Host Adapter boards - */ - -#ifndef _SCSI_AHA15_H_ -#define _SCSI_AHA15_H_ - -/* - * Addresses/length in 24 bits - * - * BEWARE: your compiler must pack these correctly, - * e.g. without gaps between two such contiguous structs - * (GCC does) - */ -typedef struct { - unsigned char msb; - unsigned char mid; - unsigned char lsb; -} aha_address_t; - -#define AHA_ADDRESS_SET(addr,val) {\ - (addr).msb = ((val) >> 16);\ - (addr).mid = ((val) >> 8);\ - (addr).lsb = (val) ;\ - } -#define AHA_ADDRESS_GET(addr,val) {\ - (val) = ((addr).msb << 16) |\ - ((addr).mid << 8) |\ - ((addr).lsb ) ;\ - } - -#define aha_length_t aha_address_t -#define AHA_LENGTH_SET AHA_ADDRESS_SET -#define AHA_LENGTH_GET AHA_ADDRESS_GET - -/* - * Register map - */ - -typedef struct { - volatile unsigned char aha_status; /* r: Status Register */ -#define aha_ctl aha_status /* w: Control Register */ - - volatile unsigned char aha_data; /* rw: Data Port */ -#define aha_cmd aha_data /* w: Command register */ - - volatile unsigned char aha_intr; /* ro: Interrupt Register */ -} aha_regmap_t; - -/* ..but on the 386 I/O is not memory mapped */ -#define AHA_STATUS_PORT(port) ((port)) -#define AHA_CONTROL_PORT(port) ((port)) -#define AHA_COMMAND_PORT(port) ((port)+1) -#define AHA_DATA_PORT(port) ((port)+1) -#define AHA_INTR_PORT(port) ((port)+2) - -/* Status Register */ -#define AHA_CSR_CMD_ERR 0x01 /* Invalid command */ -#define AHA_CSR_xxx 0x02 /* undefined */ -#define AHA_CSR_DATAI_FULL 0x04 /* In-port full */ -#define AHA_CSR_DATAO_FULL 0x08 /* Out-port full */ -#define AHA_CSR_IDLE 0x10 /* doin nuthin */ -#define AHA_CSR_INIT_REQ 0x20 /* initialization required */ -#define AHA_CSR_DIAG_FAIL 0x40 /* selftest failed */ -#define AHA_CSR_SELF_TEST 0x80 /* selftesting */ - -/* Control Register */ -#define AHA_CTL_xxx 0x0f /* undefined */ -#define AHA_CTL_SCSI_RST 0x10 /* reset SCSIbus */ -#define AHA_CTL_INTR_CLR 0x20 /* Clear interrupt reg */ -#define AHA_CTL_SOFT_RESET 0x40 /* Board only, no selftest */ -#define AHA_CTL_HARD_RESET 0x80 /* Full reset, and SCSIbus */ - -/* Interrupt Flags register */ -#define AHA_INTR_MBI_FULL 0x01 /* scan the In mboxes */ -#define AHA_INTR_MBO_AVAIL 0x02 /* scan the Out mboxes */ -#define AHA_INTR_DONE 0x04 /* command complete */ -#define AHA_INTR_RST 0x08 /* saw a SCSIbus reset */ -#define AHA_INTR_xxx 0x70 /* undefined */ -#define AHA_INTR_PENDING 0x80 /* Any interrupt bit set */ - -/* - * Command register - */ -#define AHA_CMD_NOP 0x00 /* */ -#define AHA_CMD_INIT 0x01 /* mbox initialization */ - /* 4 bytes follow: # of Out mboxes (x2->total), and - msb, mid, lsb of mbox address */ -struct aha_init { - unsigned char mb_count; - aha_address_t mb_ptr; -}; -#define AHA_CMD_START 0x02 /* start SCSI cmd */ -#define AHA_CMD_BIOS 0x03 -#define AHA_CMD_INQUIRY 0x04 - /* returns 4 bytes: */ -struct aha_inq { - unsigned char board_id; -# define AHA_BID_1540_B16 0x00 -# define AHA_BID_1540_B64 0x30 -# define AHA_BID_1540B 0x41 -# define AHA_BID_1640 0x42 -# define AHA_BID_1740 0x43 -# define AHA_BID_1542C 0x44 -# define AHA_BID_1542CF 0x45 /* BIOS v2.0x */ - - unsigned char options; -# define AHA_BOPT_STD 0x41 /* in 154x, standard model */ - - unsigned char frl_1; /* rev level */ - unsigned char frl_2; -}; -#define AHA_CMD_MBO_IE 0x05 - /* 1 byte follows: */ -# define AHA_MBO_DISABLE 0x00 -# define AHA_MBO_ENABLE 0x01 - -#define AHA_CMD_SET_SELTO 0x06 /* select timeout */ - /* 4 bytes follow: */ -struct aha_selto { - unsigned char enable; - char xxx; - unsigned char timeo_msb; - unsigned char timeo_lsb; -}; -#define AHA_CMD_SET_BUSON 0x07 - /* 1 byte value follows: 2..15 default 11 usecs */ -#define AHA_CMD_SET_BUSOFF 0x08 - /* 1 byte value follows: 1..64 default 4 usecs */ -#define AHA_CMD_SET_XSPEED 0x09 - /* 1 byte value follows: */ -# define AHA_DMASPEED_5Mb 0x00 -# define AHA_DMASPEED_7Mb 0x01 -# define AHA_DMASPEED_8Mb 0x02 -# define AHA_DMASPEED_10Mb 0x03 -# define AHA_DMASPEED_6Mb 0x04 - /* values in the range 80..ff encoded as follows: - bit 7 on --> custom speed - bits 6..4 read pulse width - 0 100ns - 1 150 - 2 200 - 3 250 - 4 300 - 5 350 - 6 400 - 7 450 - bit 3 strobe off time - 0 100ns - 1 150ns - bits 2..0 write pulse width - <same as read pulse> - */ -#define AHA_CMD_FIND_DEVICES 0x0a - /* returns 8 bytes, each one is a bitmask of the LUNs - available for the given target ID */ -struct aha_devs { - unsigned char tgt_luns[8]; -}; -#define AHA_CMD_GET_CONFIG 0x0b - /* returns 3 bytes: */ -struct aha_conf { - unsigned char dma_arbitration;/* bit N -> channel N */ - unsigned char intr_ch;/* bit N -> intr 9+N (but 13,16)*/ - unsigned char my_scsi_id; /* both of I and T role */ -}; -#define AHA_CMD_ENB_TGT_MODE 0x0c - /* 2 bytes follow: */ -struct aha_tgt { - unsigned char enable; - unsigned char luns; /* bitmask */ -}; - -#define AHA_CMD_GET_SETUP 0x0d - /* 1 byte follows: allocation len (N) */ - /* returns N bytes, 17 significant: */ -struct aha_setup { - BITFIELD_3( unsigned char, - initiate_SDT:1, - enable_parity:1, - res:6); - unsigned char xspeed; /* see above */ - unsigned char buson; - unsigned char busoff; - unsigned char n_mboxes;/* 0 if not initialized */ - aha_address_t mb_ptr; /* garbage if not inited */ - struct { - BITFIELD_3( unsigned char, - offset: 4, - period: 3, /* 200 + 50 * N */ - negotiated: 1); - } SDT_params[8]; - unsigned char no_disconnect; /* bitmask */ -}; - -#define AHA_CMD_WRITE_CH2 0x1a - /* 3 bytes (aha_address_t) follow for the buffer pointer */ -#define AHA_CMD_READ_CH2 0x1b - /* 3 bytes (aha_address_t) follow for the buffer pointer */ -#define AHA_CMD_WRITE_FIFO 0x1c - /* 3 bytes (aha_address_t) follow for the buffer pointer */ -#define AHA_CMD_READ_FIFO 0x1d - /* 3 bytes (aha_address_t) follow for the buffer pointer */ -#define AHA_CMD_ECHO 0x1f - /* 1 byte follows, which should then be read back */ -#define AHA_CMD_DIAG 0x20 -#define AHA_CMD_SET_OPT 0x21 - /* 2+ bytes follow: */ -struct aha_diag { - unsigned char parmlen; /* bytes to follow */ - unsigned char no_disconnect; /* bitmask */ - /* rest is undefined */ -}; - -#define AHA_EXT_BIOS 0x28 /* return extended bios info */ -#define AHA_MBX_ENABLE 0x29 /* enable mail box interface */ -struct aha_extbios { - unsigned char flags; /* Bit 3 == 1 extended bios enabled */ - unsigned char mailboxlock; /* mail box lock code to unlock it */ -}; - -/* - * Command Control Block - */ -typedef struct { - unsigned char ccb_code; -# define AHA_CCB_I_CMD 0x00 -# define AHA_CCB_T_CMD 0x01 -# define AHA_CCB_I_CMD_SG 0x02 -# define AHA_CCB_ICMD_R 0x03 -# define AHA_CCB_ICMD_SG_R 0x04 -# define AHA_CCB_BDEV_RST 0x81 - BITFIELD_4( unsigned char, - ccb_lun:3, - ccb_in:1, - ccb_out:1, - ccb_scsi_id:3); - unsigned char ccb_cmd_len; - unsigned char ccb_reqsns_len; /* if 1 no automatic reqsns*/ - aha_length_t ccb_datalen; - aha_address_t ccb_dataptr; - aha_address_t ccb_linkptr; - unsigned char ccb_linkid; - unsigned char ccb_hstatus; -# define AHA_HST_SUCCESS 0x00 -# define AHA_HST_SEL_TIMEO 0x11 -# define AHA_HST_DATA_OVRUN 0x12 -# define AHA_HST_BAD_DISCONN 0x13 -# define AHA_HST_BAD_PHASE_SEQ 0x14 -# define AHA_HST_BAD_OPCODE 0x16 -# define AHA_HST_BAD_LINK_LUN 0x17 -# define AHA_HST_INVALID_TDIR 0x18 -# define AHA_HST_DUPLICATED_CCB 0x19 -# define AHA_HST_BAD_PARAM 0x1a - - scsi2_status_byte_t ccb_status; - unsigned char ccb_xxx; - unsigned char ccb_xxx1; - scsi_command_group_5 ccb_scsi_cmd; /* cast as needed */ -} aha_ccb_t; - -/* For scatter/gather use a list of (len,ptr) segments, each field - is 3 bytes (aha_address_t) long. Max 17 segments, min 1 */ - -/* - * Ring descriptor, aka Mailbox - */ -typedef union { - - struct { - volatile unsigned char mb_cmd; /* Out mbox */ -# define mb_status mb_cmd /* In mbox */ - - aha_address_t mb_ptr; -#define AHA_MB_SET_PTR(mbx,val) AHA_ADDRESS_SET((mbx)->mb.mb_ptr,(val)) -#define AHA_MB_GET_PTR(mbx,val) AHA_ADDRESS_GET((mbx)->mb.mb_ptr,(val)) - - } mb; - - struct { /* ccb required In mbox */ - volatile unsigned char mb_cmd; - BITFIELD_4( unsigned char, - mb_lun : 3, - mb_isa_send : 1, - mb_isa_recv : 1, - mb_initiator_id : 3); - unsigned char mb_data_len_msb; - unsigned char mb_data_len_mid; - } mbt; - - unsigned int bits; /* quick access */ - -} aha_mbox_t; - -/* Out mbox, values for the mb_cmd field */ -#define AHA_MBO_FREE 0x00 -#define AHA_MBO_START 0x01 -#define AHA_MBO_ABORT 0x02 - -/* In mbox, values for the mb_status field */ -#define AHA_MBI_FREE 0x00 -#define AHA_MBI_SUCCESS 0x01 -#define AHA_MBI_ABORTED 0x02 -#define AHA_MBI_NOT_FOUND 0x03 -#define AHA_MBI_ERROR 0x04 -#define AHA_MBI_NEED_CCB 0x10 - -/* - * Scatter/gather segment lists - */ -typedef struct { - aha_length_t len; - aha_address_t ptr; -} aha_seglist_t; - -#define AHA_MAX_SEGLIST 17 /* which means max 64Kb */ -#endif /*_SCSI_AHA15_H_*/ diff --git a/scsi/adapters/scsi_aha15_hdw.c b/scsi/adapters/scsi_aha15_hdw.c deleted file mode 100644 index 5514bc5..0000000 --- a/scsi/adapters/scsi_aha15_hdw.c +++ /dev/null @@ -1,1467 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_aha15_hdw.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 6/91 - * - * Bottom layer of the SCSI driver: chip-dependent functions - * - * This file contains the code that is specific to the Adaptec - * AHA-15xx family of Intelligent SCSI Host Adapter boards: - * probing, start operation, and interrupt routine. - */ - -/* - * Since the board is "Intelligent" we do not need scripts like - * other simpler HBAs. Maybe. - */ -#include <cpus.h> -#include <platforms.h> - -#include <aha.h> -#if NAHA > 0 - -#include <mach/std_types.h> -#include <machine/machspl.h> -#include <sys/types.h> -#include <chips/busses.h> -#include <scsi/compat_30.h> - -/* #include <sys/syslog.h> */ - -#include <scsi/scsi.h> -#include <scsi/scsi2.h> -#include <scsi/scsi_defs.h> - -#include <scsi/adapters/scsi_aha15.h> - -#ifdef AT386 -#define MACHINE_PGBYTES I386_PGBYTES -#define MAPPABLE 0 -#define gimmeabreak() asm("int3") -#include <i386/pio.h> /* inlining of outb and inb */ -#endif /*AT386*/ - -#ifdef CBUS /* For the Corollary machine, physical */ -#include <i386at/mp/mp.h> -#include <cbus/cbus.h> - -#define aha_cbus_window transient_state.hba_dep[0] - /* must use windows for phys addresses */ - /* greater than 16 megs */ - -#define kvtoAT cbus_kvtoAT -#else /* CBUS */ -#define kvtoAT kvtophys -#endif /* CBUS */ - -#ifndef MACHINE_PGBYTES /* cross compile check */ -#define MACHINE_PGBYTES 0x1000 -#define MAPPABLE 1 -#define gimmeabreak() Debugger("gimmeabreak"); -#endif - -/* - * Data structures: ring, ccbs, a per target buffer - */ - -#define AHA_NMBOXES 2 /* no need for more, I think */ -struct aha_mb_ctl { - aha_mbox_t omb[AHA_NMBOXES]; - aha_mbox_t imb[AHA_NMBOXES]; - unsigned char iidx, oidx; /* roving ptrs into */ -}; -#define next_mbx_idx(i) ((((i)+1)==AHA_NMBOXES)?0:((i)+1)) - -#define AHA_NCCB 8 /* for now */ -struct aha_ccb_raw { - target_info_t *active_target; - aha_ccb_t ccb; - char buffer[256]; /* separate out this ? */ -}; -#define rccb_to_cmdptr(rccb) ((char*)&((rccb)->ccb.ccb_scsi_cmd)) - -/* forward decls */ -int aha_reset_scsibus(); -boolean_t aha_probe_target(); - -/* - * State descriptor for this layer. There is one such structure - * per (enabled) board - */ -struct aha_softc { - watchdog_t wd; - decl_simple_lock_data(, aha_lock) - unsigned int port; /* I/O port */ - - int ntargets; /* how many alive on this scsibus */ - - scsi_softc_t *sc; /* HBA-indep info */ - - struct aha_mb_ctl mb; /* mailbox structures */ - - /* This chicanery is for mapping back the phys address - of a CCB (which we get in an MBI) to its virtual */ - /* [we could use phystokv(), but it isn't standard] */ - vm_offset_t I_hold_my_phys_address; - struct aha_ccb_raw aha_ccbs[AHA_NCCB]; - -} aha_softc_data[NAHA]; - -typedef struct aha_softc *aha_softc_t; - -aha_softc_t aha_softc[NAHA]; - -struct aha_ccb_raw * -mb_to_rccb(aha, mbi) - aha_softc_t aha; - aha_mbox_t mbi; -{ - vm_offset_t addr; - - AHA_MB_GET_PTR(&mbi,addr); /* phys address of ccb */ - - /* make virtual */ - addr = ((vm_offset_t)&aha->I_hold_my_phys_address) + - (addr - aha->I_hold_my_phys_address); - - /* adjust by proper offset to get base */ - addr -= (vm_offset_t)&(((struct aha_ccb_raw *)0)->ccb); - - return (struct aha_ccb_raw *)addr; -} - -target_info_t * -aha_tgt_alloc(aha, id, sns_len, tgt) - aha_softc_t aha; - target_info_t *tgt; -{ - struct aha_ccb_raw *rccb; - - aha->ntargets++; - - if (tgt == 0) - tgt = scsi_slave_alloc(aha - aha_softc_data, id, aha); - - rccb = &(aha->aha_ccbs[id]); - rccb->ccb.ccb_reqsns_len = sns_len; - tgt->cmd_ptr = rccb_to_cmdptr(rccb); - tgt->dma_ptr = 0; -#ifdef CBUS - tgt->aha_cbus_window = 0; -#endif /* CBUS */ - return tgt; -} - -/* - * Synch xfer timing conversions - */ -#define aha_to_scsi_period(a) ((200 + ((a) * 50)) >> 2) -#define scsi_period_to_aha(p) ((((p) << 2) - 200) / 50) - -/* - * Definition of the controller for the auto-configuration program. - */ - -/* DOCUMENTATION */ -/* base ports can be: - 0x334, 0x330 (default), 0x234, 0x230, 0x134, 0x130 - possible interrupt channels are: - 9, 10, 11 (default), 12, 14, 15 - DMA channels can be: - 7, 6, 5 (default), 0 -/* DOCUMENTATION */ - -int aha_probe(), scsi_slave(), aha_go(), aha_intr(); -void scsi_attach(); - -vm_offset_t aha_std[NAHA] = { 0 }; -struct bus_device *aha_dinfo[NAHA*8]; -struct bus_ctlr *aha_minfo[NAHA]; -struct bus_driver aha_driver = - { aha_probe, scsi_slave, scsi_attach, aha_go, aha_std, "rz", aha_dinfo, - "ahac", aha_minfo, BUS_INTR_B4_PROBE}; - -#define DEBUG 1 -#if DEBUG - -#define PRINT(x) if (scsi_debug) printf x - -aha_state(port) -{ - register unsigned char st, intr; - - if (port == 0) - port = 0x330; - st = inb(AHA_STATUS_PORT(port)); - intr = inb(AHA_INTR_PORT(port)); - - printf("status %x intr %x\n", st, intr); - return 0; -} - -aha_target_state(tgt) - target_info_t *tgt; -{ - if (tgt == 0) - tgt = aha_softc[0]->sc->target[0]; - if (tgt == 0) - return 0; - printf("fl %x dma %X+%x cmd %x@%X id %x per %x off %x ior %X ret %X\n", - tgt->flags, tgt->dma_ptr, tgt->transient_state.dma_offset, tgt->cur_cmd, - tgt->cmd_ptr, tgt->target_id, tgt->sync_period, tgt->sync_offset, - tgt->ior, tgt->done); - - return 0; -} - -aha_all_targets(unit) -{ - int i; - target_info_t *tgt; - for (i = 0; i < 8; i++) { - tgt = aha_softc[unit]->sc->target[i]; - if (tgt) - aha_target_state(tgt); - } -} - -#define TRMAX 200 -int tr[TRMAX+3]; -int trpt, trpthi; -#define TR(x) tr[trpt++] = x -#define TRWRAP trpthi = trpt; trpt = 0; -#define TRCHECK if (trpt > TRMAX) {TRWRAP} - -#define TRACE - -#ifdef TRACE - -#define LOGSIZE 256 -#define LOG_KERN 0<<3 /* from syslog.h */ - -int aha_logpt; -char aha_log[LOGSIZE]; - -#define MAXLOG_VALUE 0x1e -struct { - char *name; - unsigned int count; -} logtbl[MAXLOG_VALUE]; - -static LOG(e,f) - char *f; -{ - aha_log[aha_logpt++] = (e); - if (aha_logpt == LOGSIZE) aha_logpt = 0; - if ((e) < MAXLOG_VALUE) { - logtbl[(e)].name = (f); - logtbl[(e)].count++; - } -} - -aha_print_log(skip) - int skip; -{ - register int i, j; - register unsigned char c; - - for (i = 0, j = aha_logpt; i < LOGSIZE; i++) { - c = aha_log[j]; - if (++j == LOGSIZE) j = 0; - if (skip-- > 0) - continue; - if (c < MAXLOG_VALUE) - printf(" %s", logtbl[c].name); - else - printf("-%x", c & 0x7f); - } - return 0; -} - -aha_print_stat() -{ - register int i; - register char *p; - for (i = 0; i < MAXLOG_VALUE; i++) { - if (p = logtbl[i].name) - printf("%d %s\n", logtbl[i].count, p); - } -} - -#else /*TRACE*/ -#define LOG(e,f) -#define LOGSIZE -#endif /*TRACE*/ - -#else /*DEBUG*/ -#define PRINT(x) -#define LOG(e,f) -#define LOGSIZE -#define TRCHECK -#define TR(a) - -#endif /*DEBUG*/ - -/* Utility functions at end */ - - -/* - * Probe/Slave/Attach functions - */ - -int aha_dotarget = 1; /* somehow on some boards this is trouble */ - -/* - * Probe routine: - * Should find out (a) if the controller is - * present and (b) which/where slaves are present. - * - * Implementation: - * Just ask the board to do it - */ -aha_probe(port, ui) - register port; - struct bus_ctlr *ui; -{ - int unit = ui->unit; - aha_softc_t aha = &aha_softc_data[unit]; - int target_id; - scsi_softc_t *sc; - spl_t s; - boolean_t did_banner = FALSE; - struct aha_devs installed; - struct aha_conf conf; - - /* No interrupts yet */ - s = splbio(); - - /* - * We should be called with a sensible port, but you never know. - * Send an echo command and see that we get it back properly - */ - { - register unsigned char st; - - st = inb(AHA_STATUS_PORT(port)); - - /* - * There is no board reset in case of reboot with - * no power-on/power-off sequence. Test it and do - * the reset if necessary. - */ - - if (!(st & AHA_CSR_INIT_REQ)) { - outb(AHA_CONTROL_PORT(port), - AHA_CTL_SOFT_RESET|AHA_CTL_HARD_RESET); - while ((st = inb(AHA_STATUS_PORT(port))) & - AHA_CSR_SELF_TEST); - } - if ((st & AHA_CSR_DATAO_FULL) || - !(st & AHA_CSR_INIT_REQ)) - goto fail; - - outb(AHA_COMMAND_PORT(port), AHA_CMD_ECHO); - delay(1000);/*?*/ - st = inb(AHA_STATUS_PORT(port)); - if (st & (AHA_CSR_CMD_ERR|AHA_CSR_DATAO_FULL)) - goto fail; - - outb(AHA_COMMAND_PORT(port), 0x5e); - delay(1000); - - st = inb(AHA_STATUS_PORT(port)); - if ((st & AHA_CSR_CMD_ERR) || - ((st & AHA_CSR_DATAI_FULL) == 0)) - goto fail; - - st = inb(AHA_DATA_PORT(port)); - if (st != 0x5e) { -fail: splx(s); - return 0; - } - /* - * augment test with check for echoing inverse and with - * test for enhanced adapter with standard ports enabled. - */ - - /* Check that 0xa1 echoed as well as 0x5e */ - - outb(AHA_COMMAND_PORT(port), AHA_CMD_ECHO); - delay(1000);/*?*/ - st = inb(AHA_STATUS_PORT(port)); - if (st & (AHA_CSR_CMD_ERR|AHA_CSR_DATAO_FULL)) - goto fail; - - outb(AHA_COMMAND_PORT(port), 0xa1); - delay(1000); - - st = inb(AHA_STATUS_PORT(port)); - if ((st & AHA_CSR_CMD_ERR) || - ((st & AHA_CSR_DATAI_FULL) == 0)) - goto fail; - - st = inb(AHA_DATA_PORT(port)); - if (st != 0xa1) - goto fail ; - - { /* Check that port isn't 174x in enhanced mode - with standard mode ports enabled. This should be - ignored because it will be caught and correctly - handled by eaha_probe(). See TRM4-11..13. - dph - */ - unsigned z ; - static unsigned port_table[] = - {0,0,0x130,0x134,0x230,0x234,0x330,0x334}; - for (z= 0x1000; z<= 0xF000; z+= 0x1000) - if (inb(z+0xC80) == 0x04 && - inb(z+0xC81) == 0x90 && - inb(z+0xCC0) & 0x80 == 0x80 && - port_table [inb(z+0xCC0) & 0x07] == port) - goto fail ; - } - outb(AHA_CONTROL_PORT(port), AHA_CTL_INTR_CLR); - } - -#if MAPPABLE - /* Mappable version side */ - AHA_probe(port, ui); -#endif /*MAPPABLE*/ - - /* - * Initialize hw descriptor, cache some pointers - */ - aha_softc[unit] = aha; - aha->port = port; - - sc = scsi_master_alloc(unit, aha); - aha->sc = sc; - - simple_lock_init(&aha->aha_lock); - sc->go = aha_go; - sc->watchdog = scsi_watchdog; - sc->probe = aha_probe_target; - aha->wd.reset = aha_reset_scsibus; - - /* Stupid limitation, no way around it */ - sc->max_dma_data = (AHA_MAX_SEGLIST-1) * MACHINE_PGBYTES; - - - /* XXX - * I'm not sure how much use this bit of code is really. - * On the 1542CF we don't really want to try and initialize - * the mailboxes before unlocking them in any case, and - * resetting the card is done above. - */ -#if 0 -#if 0 - /* - * Reset board. - */ - aha_reset(port, TRUE); -#else - /* - * Initialize mailboxes - */ - aha_init_1(aha); -#endif -#endif - - /* - * Who are we ? - */ - { - struct aha_inq inq; - struct aha_extbios extbios; - char *id; - - aha_command(port, AHA_CMD_INQUIRY, 0, 0, &inq, sizeof(inq), TRUE); - - switch (inq.board_id) { - case AHA_BID_1540_B16: - case AHA_BID_1540_B64: - id = "1540"; break; - case AHA_BID_1540B: - id = "1540B/1542B"; break; - case AHA_BID_1640: - id = "1640"; break; - case AHA_BID_1740: - id = "1740 Unsupported!!"; break; - case AHA_BID_1542C: - id = "1542C"; aha_dotarget = 0; break; - case AHA_BID_1542CF: - id = "1542CF"; break; - default: - id = 0; break; - } - - printf("Adaptec %s [id %x], rev %c%c, options x%x\n", - id ? id : "Board", - inq.board_id, inq.frl_1, inq.frl_2, inq.options); - - /* - * If we are a 1542C or 1542CF disable the extended bios - * so that the mailbox interface is unlocked. - * No need to check the extended bios flags as some of the - * extensions that cause us problems are not flagged in - * that byte. - */ - if (inq.board_id == 0x44 || inq.board_id == 0x45) { - aha_command(port, AHA_EXT_BIOS, 0, 0, &extbios, - sizeof(extbios), TRUE); -#ifdef AHADEBUG - printf("aha: extended bios flags 0x%x\n", extbios.flags); - printf("aha: mailboxlock 0x%x\n", extbios.mblock); -#endif /* AHADEBUG */ - - printf("aha: 1542C/CF detected, unlocking mailbox\n"); - - /* XXX - This sends the mailboxlock code out to the - * controller. We need to output a 0, then the - * code...so since we don't care about the flags - * anyway, we just zero out that field and re-use - * the struct. - */ - extbios.flags = 0; - aha_command(port, AHA_MBX_ENABLE, &extbios, - sizeof(extbios), 0, 0, TRUE); - } - - } -doconf: - /* - * Readin conf data - */ - aha_command(port, AHA_CMD_GET_CONFIG, 0, 0, &conf, sizeof(conf), TRUE); - - { - unsigned char args; - - /* - * Change the bus on/off times to not clash with - * other dma users. - */ - args = 7; - aha_command(port, AHA_CMD_SET_BUSON, &args, 1, 0, 0, TRUE); - args = 5; - aha_command(port, AHA_CMD_SET_BUSOFF, &args, 1, 0, 0, TRUE); - } - - /* XXX - This is _REALLY_ sickening. */ - /* - * Set up the DMA channel we'll be using. - */ - { - register int d, i; - static struct { - unsigned char port; - unsigned char init_data; - } aha_dma_init[8][2] = { - {{0x0b,0x0c}, {0x0a,0x00}}, /* channel 0 */ - {{0,0},{0,0}}, - {{0,0},{0,0}}, - {{0,0},{0,0}}, - {{0,0},{0,0}}, - {{0xd6,0xc1}, {0xd4,0x01}}, /* channel 5 (def) */ - {{0xd6,0xc2}, {0xd4,0x02}}, /* channel 6 */ - {{0xd6,0xc3}, {0xd4,0x03}} /* channel 7 */ - }; - - - for (i = 0; i < 8; i++) - if ((1 << i) & conf.intr_ch) break; - i += 9; - -#if there_was_a_way - /* - * On second unit, avoid clashes with first - */ - if ((unit > 0) && (ui->sysdep1 != i)) { - printf("Reprogramming irq and dma ch..\n"); - .... - goto doconf; - } -#endif - - /* - * Initialize the DMA controller viz the channel we'll use - */ - for (d = 0; d < 8; d++) - if ((1 << d) & conf.dma_arbitration) break; - - outb(aha_dma_init[d][0].port, aha_dma_init[d][0].init_data); - outb(aha_dma_init[d][1].port, aha_dma_init[d][1].init_data); - - /* make mapping phys->virt possible for CCBs */ - aha->I_hold_my_phys_address = - kvtoAT((vm_offset_t)&aha->I_hold_my_phys_address); - - /* - * Our SCSI ID. (xxx) On some boards this is SW programmable. - */ - sc->initiator_id = conf.my_scsi_id; - - printf("%s%d: [dma ch %d intr ch %d] my SCSI id is %d", - ui->name, unit, d, i, sc->initiator_id); - - /* Interrupt vector setup */ - ui->sysdep1 = i; - take_ctlr_irq(ui); - } - - /* - * More initializations - */ - { - register target_info_t *tgt; - - aha_init(aha); - - /* allocate a desc for tgt mode role */ - tgt = aha_tgt_alloc(aha, sc->initiator_id, 1, 0); - sccpu_new_initiator(tgt, tgt); /* self */ - - } - - /* Now we could take interrupts, BUT we do not want to - be selected as targets by some other host just yet */ - - /* - * For all possible targets, see if there is one and allocate - * a descriptor for it if it is there. - * This includes ourselves, when acting as target - */ - aha_command( port, AHA_CMD_FIND_DEVICES, 0, 0, &installed, sizeof(installed), TRUE); - for (target_id = 0; target_id < 8; target_id++) { - - if (target_id == sc->initiator_id) /* done already */ - continue; - - if (installed.tgt_luns[target_id] == 0) - continue; - - printf(",%s%d", did_banner++ ? " " : " target(s) at ", - target_id); - - /* Normally, only LUN 0 */ - if (installed.tgt_luns[target_id] != 1) - printf("(%x)", installed.tgt_luns[target_id]); - /* - * Found a target - */ - (void) aha_tgt_alloc(aha, target_id, 1/*no REQSNS*/, 0); - - } - printf(".\n"); - splx(s); - - return 1; -} - -boolean_t -aha_probe_target(tgt, ior) - target_info_t *tgt; - io_req_t ior; -{ - aha_softc_t aha = aha_softc[tgt->masterno]; - boolean_t newlywed; - - newlywed = (tgt->cmd_ptr == 0); - if (newlywed) { - /* desc was allocated afresh */ - (void) aha_tgt_alloc(aha,tgt->target_id, 1/*no REQSNS*/, tgt); - } - - if (scsi_inquiry(tgt, SCSI_INQ_STD_DATA) == SCSI_RET_DEVICE_DOWN) - return FALSE; - - tgt->flags = TGT_ALIVE; - return TRUE; -} - -aha_reset(port, quick) -{ - register unsigned char st; - - /* - * Reset board and wait till done - */ - outb(AHA_CONTROL_PORT(port), AHA_CTL_SOFT_RESET); - do { - delay(25); - st = inb(AHA_STATUS_PORT(port)); - } while ((st & (AHA_CSR_IDLE|AHA_CSR_INIT_REQ)) == 0); - - if (quick) return; - - /* - * reset the scsi bus. Does NOT generate an interrupt (bozos) - */ - outb(AHA_CONTROL_PORT(port), AHA_CTL_SCSI_RST); -} - -aha_init_1(aha) - aha_softc_t aha; -{ - struct aha_init a; - vm_offset_t phys; - - bzero(&aha->mb, sizeof(aha->mb)); /* also means all free */ - a.mb_count = AHA_NMBOXES; - phys = kvtoAT((vm_offset_t)&aha->mb); - AHA_ADDRESS_SET(a.mb_ptr, phys); - aha_command(aha->port, AHA_CMD_INIT, &a, sizeof(a), 0, 0, TRUE); -} - -aha_init_2(port) -{ - unsigned char disable = AHA_MBO_DISABLE; - struct aha_tgt role; - - /* Disable MBO available interrupt */ - aha_command(port, AHA_CMD_MBO_IE, &disable, 1, 0,0, FALSE); - - if (aha_dotarget) { - /* Enable target mode role */ - role.enable = 1; - role.luns = 1; /* only LUN 0 */ - aha_command(port, AHA_CMD_ENB_TGT_MODE, &role, sizeof(role), 0, 0, TRUE); - } -} - -aha_init(aha) - aha_softc_t aha; -{ - aha_init_1(aha); - aha_init_2(aha->port); -} - -/* - * Operational functions - */ - -/* - * Start a SCSI command on a target - */ -aha_go(tgt, cmd_count, in_count, cmd_only) - target_info_t *tgt; - boolean_t cmd_only; -{ - aha_softc_t aha; - spl_t s; - struct aha_ccb_raw *rccb; - int len; - vm_offset_t virt, phys; - -#if CBUS - at386_io_lock_state(); -#endif - - LOG(1,"go"); - - aha = (aha_softc_t)tgt->hw_state; - -/* XXX delay the handling of the ccb till later */ - rccb = &(aha->aha_ccbs[tgt->target_id]); - rccb->active_target = tgt; - - /* - * We can do real DMA. - */ -/* tgt->transient_state.copy_count = 0; unused */ -/* tgt->transient_state.dma_offset = 0; unused */ - - tgt->transient_state.cmd_count = cmd_count; - - if ((tgt->cur_cmd == SCSI_CMD_WRITE) || - (tgt->cur_cmd == SCSI_CMD_LONG_WRITE)){ - io_req_t ior = tgt->ior; - register int len = ior->io_count; - - tgt->transient_state.out_count = len; - - /* How do we avoid leaks here ? Trust the board - will do zero-padding, for now. XXX CHECKME */ -#if 0 - if (len < tgt->block_size) { - bzero(to + len, tgt->block_size - len); - len = tgt->block_size; - tgt->transient_state.out_count = len; - } -#endif - } else { - tgt->transient_state.out_count = 0; - } - - /* See above for in_count < block_size */ - tgt->transient_state.in_count = in_count; - - /* - * Setup CCB state - */ - tgt->done = SCSI_RET_IN_PROGRESS; - - switch (tgt->cur_cmd) { - case SCSI_CMD_READ: - case SCSI_CMD_LONG_READ: - LOG(9,"readop"); - virt = (vm_offset_t)tgt->ior->io_data; - len = tgt->transient_state.in_count; - rccb->ccb.ccb_in = 1; rccb->ccb.ccb_out = 0; - break; - case SCSI_CMD_WRITE: - case SCSI_CMD_LONG_WRITE: - LOG(0x1a,"writeop"); - virt = (vm_offset_t)tgt->ior->io_data; - len = tgt->transient_state.out_count; - rccb->ccb.ccb_in = 0; rccb->ccb.ccb_out = 1; - break; - case SCSI_CMD_INQUIRY: - case SCSI_CMD_REQUEST_SENSE: - case SCSI_CMD_MODE_SENSE: - case SCSI_CMD_RECEIVE_DIAG_RESULTS: - case SCSI_CMD_READ_CAPACITY: - case SCSI_CMD_READ_BLOCK_LIMITS: - case SCSI_CMD_READ_TOC: - case SCSI_CMD_READ_SUBCH: - case SCSI_CMD_READ_HEADER: - case 0xc4: /* despised: SCSI_CMD_DEC_PLAYBACK_STATUS */ - case 0xc6: /* despised: SCSI_CMD_TOSHIBA_READ_SUBCH_Q */ - case 0xc7: /* despised: SCSI_CMD_TOSHIBA_READ_TOC_ENTRY */ - case 0xdd: /* despised: SCSI_CMD_NEC_READ_SUBCH_Q */ - case 0xde: /* despised: SCSI_CMD_NEC_READ_TOC */ - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - virt = (vm_offset_t)tgt->cmd_ptr; - len = tgt->transient_state.in_count; - rccb->ccb.ccb_in = 1; rccb->ccb.ccb_out = 0; - break; - case SCSI_CMD_MODE_SELECT: - case SCSI_CMD_REASSIGN_BLOCKS: - case SCSI_CMD_FORMAT_UNIT: - case 0xc9: /* vendor-spec: SCSI_CMD_DEC_PLAYBACK_CONTROL */ - { register int cs = sizeof_scsi_command(tgt->cur_cmd); - tgt->transient_state.cmd_count = cs; - len = - tgt->transient_state.out_count = cmd_count - cs; - virt = (vm_offset_t)tgt->cmd_ptr + cs; - rccb->ccb.ccb_in = 0; rccb->ccb.ccb_out = 1; - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - } - break; - default: - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - virt = 0; - len = 0; - rccb->ccb.ccb_in = 0; rccb->ccb.ccb_out = 0; - } - -#if CBUS - at386_io_lock(MP_DEV_WAIT); -#endif - aha_prepare_rccb(tgt, rccb, virt, len); - - rccb->ccb.ccb_lun = tgt->lun; - rccb->ccb.ccb_scsi_id = tgt->target_id; - -/* AHA_LENGTH_SET(rccb->ccb.ccb_linkptr, 0); unused */ -/* rccb->ccb.ccb_linkid = 0; unused */ - -#if !CBUS - s = splbio(); -#endif - - LOG(3,"enqueue"); - - aha_start_scsi(aha, &rccb->ccb); - -#if CBUS - at386_io_unlock(); -#else - splx(s); -#endif -} - -aha_prepare_rccb(tgt, rccb, virt, len) - target_info_t *tgt; - struct aha_ccb_raw *rccb; - vm_offset_t virt; - vm_size_t len; -{ - vm_offset_t phys; -#ifdef CBUS - int cbus_window; -#endif /* CBUS */ - - rccb->ccb.ccb_cmd_len = tgt->transient_state.cmd_count; - - /* this opcode is refused, grrrr. */ -/* rccb->ccb.ccb_code = AHA_CCB_I_CMD_R; /* default common case */ - rccb->ccb.ccb_code = AHA_CCB_I_CMD; /* default common case */ - AHA_LENGTH_SET(rccb->ccb.ccb_datalen, len);/* default common case */ - -#ifdef CBUS - if (tgt->aha_cbus_window == 0) - tgt->aha_cbus_window = cbus_alloc_win(AHA_MAX_SEGLIST+1); - cbus_window = tgt->aha_cbus_window; -#endif /* CBUS */ - - if (virt == 0) { - /* no xfers */ - AHA_ADDRESS_SET(rccb->ccb.ccb_dataptr, 0); - } else if (len <= MACHINE_PGBYTES) { -/* INCORRECT: what if across two pages :INCORRECT */ - /* simple xfer */ -#ifdef CBUS - phys = cbus_kvtoAT_ww(virt, cbus_window); -#else /* CBUS */ - phys = kvtophys(virt); -#endif /* CBUS */ - AHA_ADDRESS_SET(rccb->ccb.ccb_dataptr, phys); - } else { - /* messy xfer */ - aha_seglist_t *seglist; - vm_offset_t ph1, off; - vm_size_t l1; - - /* this opcode does not work, grrrrr */ -/* rccb->ccb.ccb_code = AHA_CCB_I_CMD_SG_R;*/ - rccb->ccb.ccb_code = AHA_CCB_I_CMD_SG; - - if (tgt->dma_ptr == 0) - aha_alloc_segment_list(tgt); - seglist = (aha_seglist_t *) tgt->dma_ptr; -#ifdef CBUS - phys = cbus_kvtoAT_ww(seglist, cbus_window); - cbus_window++; -#else /* CBUS */ - phys = kvtophys((vm_offset_t) seglist); -#endif /* CBUS */ - AHA_ADDRESS_SET(rccb->ccb.ccb_dataptr, phys); - - ph1 = /*i386_trunc_page*/ virt & ~(MACHINE_PGBYTES - 1); - off = virt & (MACHINE_PGBYTES - 1); -#ifdef CBUS - ph1 = cbus_kvtoAT_ww(ph1, cbus_window) + off; - cbus_window++; -#else /* CBUS */ - ph1 = kvtophys(ph1) + off; -#endif /* CBUS */ - l1 = MACHINE_PGBYTES - off; - - off = 1;/* now #pages */ - while (1) { - AHA_ADDRESS_SET(seglist->ptr, ph1); - AHA_LENGTH_SET(seglist->len, l1); - seglist++; - - if ((len -= l1) <= 0) - break; - virt += l1; off++; - -#ifdef CBUS - ph1 = cbus_kvtoAT_ww(virt, cbus_window); - cbus_window++; -#else /* CBUS */ - ph1 = kvtophys(virt); -#endif /* CBUS */ - l1 = (len > MACHINE_PGBYTES) ? MACHINE_PGBYTES : len; - } - l1 = off * sizeof(*seglist); - AHA_LENGTH_SET(rccb->ccb.ccb_datalen, l1); - } -} - -aha_start_scsi(aha, ccb) - aha_softc_t aha; - aha_ccb_t *ccb; -{ - register aha_mbox_t *mb; - register idx; - vm_offset_t phys; - aha_mbox_t mbo; - spl_t s; - - LOG(4,"start"); - LOG(0x80+ccb->ccb_scsi_id,0); - - /* - * Get an MBO, spin if necessary (takes little time) - */ - s = splbio(); - phys = kvtoAT((vm_offset_t)ccb); - /* might cross pages, but should be ok (kernel is contig) */ - AHA_MB_SET_PTR(&mbo,phys); - mbo.mb.mb_cmd = AHA_MBO_START; - - simple_lock(&aha->aha_lock); - if (aha->wd.nactive++ == 0) - aha->wd.watchdog_state = SCSI_WD_ACTIVE; - idx = aha->mb.oidx; - aha->mb.oidx = next_mbx_idx(idx); - mb = &aha->mb.omb[idx]; - while (mb->mb.mb_status != AHA_MBO_FREE) - delay(1); - mb->bits = mbo.bits; - simple_unlock(&aha->aha_lock); - - /* - * Start the board going - */ - aha_command(aha->port, AHA_CMD_START, 0, 0, 0, 0, FALSE); - splx(s); -} - -/* - * Interrupt routine - * Take interrupts from the board - * - * Implementation: - * TBD - */ -aha_intr(unit) -{ - register aha_softc_t aha; - register port; - register csr, intr; -#if MAPPABLE - extern boolean_t rz_use_mapped_interface; - - if (rz_use_mapped_interface) - return AHA_intr(unit); -#endif /*MAPPABLE*/ - - aha = aha_softc[unit]; - port = aha->port; - - LOG(5,"\n\tintr"); -gotintr: - /* collect ephemeral information */ - csr = inb(AHA_STATUS_PORT(port)); - intr = inb(AHA_INTR_PORT(port)); - - /* - * Check for errors - */ - if (csr & (AHA_CSR_DIAG_FAIL|AHA_CSR_CMD_ERR)) { -/* XXX */ gimmeabreak(); - } - - /* drop spurious interrupts */ - if ((intr & AHA_INTR_PENDING) == 0) { - LOG(2,"SPURIOUS"); - return; - } - outb(AHA_CONTROL_PORT(port), AHA_CTL_INTR_CLR); - -TR(csr);TR(intr);TRCHECK - - if (intr & AHA_INTR_RST) - return aha_bus_reset(aha); - - /* we got an interrupt allright */ - if (aha->wd.nactive) - aha->wd.watchdog_state = SCSI_WD_ACTIVE; - - if (intr == AHA_INTR_DONE) { - /* csr & AHA_CSR_CMD_ERR --> with error */ - LOG(6,"done"); - return; - } - -/* if (intr & AHA_INTR_MBO_AVAIL) will not happen */ - - /* Some real work today ? */ - if (intr & AHA_INTR_MBI_FULL) { - register int idx; - register aha_mbox_t *mb; - int nscan = 0; - aha_mbox_t mbi; -rescan: - simple_lock(&aha->aha_lock); - idx = aha->mb.iidx; - aha->mb.iidx = next_mbx_idx(idx); - mb = &aha->mb.imb[idx]; - mbi.bits = mb->bits; - mb->mb.mb_status = AHA_MBI_FREE; - simple_unlock(&aha->aha_lock); - - nscan++; - - switch (mbi.mb.mb_status) { - - case AHA_MBI_FREE: - if (nscan >= AHA_NMBOXES) - return; - goto rescan; - break; - - case AHA_MBI_SUCCESS: - case AHA_MBI_ERROR: - aha_initiator_intr(aha, mbi); - break; - - case AHA_MBI_NEED_CCB: - aha_target_intr(aha, mbi); - break; - -/* case AHA_MBI_ABORTED: /* this we wont see */ -/* case AHA_MBI_NOT_FOUND: /* this we wont see */ - default: - log( LOG_KERN, - "aha%d: Bogus status (x%x) in MBI\n", - unit, mbi.mb.mb_status); - break; - } - - /* peek ahead */ - if (aha->mb.imb[aha->mb.iidx].mb.mb_status != AHA_MBI_FREE) - goto rescan; - } - - /* See if more work ready */ - if (inb(AHA_INTR_PORT(port)) & AHA_INTR_PENDING) { - LOG(7,"\n\tre-intr"); - goto gotintr; - } -} - -/* - * The interrupt routine turns to one of these two - * functions, depending on the incoming mbi's role - */ -aha_target_intr(aha, mbi) - aha_softc_t aha; - aha_mbox_t mbi; -{ - target_info_t *initiator; /* this is the caller */ - target_info_t *self; /* this is us */ - int len; - - if (mbi.mbt.mb_cmd != AHA_MBI_NEED_CCB) - gimmeabreak(); - - /* If we got here this is not zero .. */ - self = aha->sc->target[aha->sc->initiator_id]; - - initiator = aha->sc->target[mbi.mbt.mb_initiator_id]; - /* ..but initiators are not required to answer to our inquiry */ - if (initiator == 0) { - /* allocate */ - initiator = aha_tgt_alloc(aha, mbi.mbt.mb_initiator_id, - sizeof(scsi_sense_data_t) + 5, 0); - - /* We do not know here wether the host was down when - we inquired, or it refused the connection. Leave - the decision on how we will talk to it to higher - level code */ - LOG(0xC, "new_initiator"); - sccpu_new_initiator(self, initiator); - } - - /* The right thing to do would be build an ior - and call the self->dev_ops->strategy routine, - but we cannot allocate it at interrupt level. - Also note that we are now disconnected from the - initiator, no way to do anything else with it - but reconnect and do what it wants us to do */ - - /* obviously, this needs both spl and MP protection */ - self->dev_info.cpu.req_pending = TRUE; - self->dev_info.cpu.req_id = mbi.mbt.mb_initiator_id; - self->dev_info.cpu.req_lun = mbi.mbt.mb_lun; - self->dev_info.cpu.req_cmd = - mbi.mbt.mb_isa_send ? SCSI_CMD_SEND: SCSI_CMD_RECEIVE; - len = (mbi.mbt.mb_data_len_msb << 16) | - (mbi.mbt.mb_data_len_mid << 8 ); - len += 0x100;/* truncation problem */ - self->dev_info.cpu.req_len = len; - - LOG(0xB,"tgt-mode-restart"); - (*self->dev_ops->restart)( self, FALSE); - - /* The call above has either prepared the data, - placing an ior on self, or it handled it some - other way */ - if (self->ior == 0) - return; /* I guess we'll do it later */ - - { - struct aha_ccb_raw *rccb; - - rccb = &(aha->aha_ccbs[initiator->target_id]); - rccb->active_target = initiator; - if (self->dev_info.cpu.req_cmd == SCSI_CMD_SEND) { - rccb->ccb.ccb_in = 1; - rccb->ccb.ccb_out = 0; - } else { - rccb->ccb.ccb_in = 0; - rccb->ccb.ccb_out = 1; - } - - aha_prepare_rccb(initiator, rccb, - (vm_offset_t)self->ior->io_data, self->ior->io_count); - rccb->ccb.ccb_code = AHA_CCB_T_CMD; - rccb->ccb.ccb_lun = initiator->lun; - rccb->ccb.ccb_scsi_id = initiator->target_id; - - simple_lock(&aha->aha_lock); - if (aha->wd.nactive++ == 0) - aha->wd.watchdog_state = SCSI_WD_ACTIVE; - simple_unlock(&aha->aha_lock); - - aha_start_scsi(aha, &rccb->ccb); - } -} - -aha_initiator_intr(aha, mbi) - aha_softc_t aha; - aha_mbox_t mbi; -{ - struct aha_ccb_raw *rccb; - scsi2_status_byte_t status; - target_info_t *tgt; - - rccb = mb_to_rccb(aha,mbi); - tgt = rccb->active_target; - rccb->active_target = 0; - - /* shortcut (sic!) */ - if (mbi.mb.mb_status == AHA_MBI_SUCCESS) - goto allok; - - switch (rccb->ccb.ccb_hstatus) { - case AHA_HST_SUCCESS: -allok: - status = rccb->ccb.ccb_status; - if (status.st.scsi_status_code != SCSI_ST_GOOD) { - scsi_error(tgt, SCSI_ERR_STATUS, status.bits, 0); - tgt->done = (status.st.scsi_status_code == SCSI_ST_BUSY) ? - SCSI_RET_RETRY : SCSI_RET_NEED_SENSE; - } else - tgt->done = SCSI_RET_SUCCESS; - break; - case AHA_HST_SEL_TIMEO: - if (tgt->flags & TGT_FULLY_PROBED) - tgt->flags = 0; /* went offline */ - tgt->done = SCSI_RET_DEVICE_DOWN; - break; - case AHA_HST_DATA_OVRUN: - /* BUT we don't know if this is an underrun. - It is ok if we get less data than we asked - for, in a number of cases. Most boards do not - seem to generate this anyways, but some do. */ - { register int cmd = tgt->cur_cmd; - switch (cmd) { - case SCSI_CMD_INQUIRY: - case SCSI_CMD_REQUEST_SENSE: - break; - default: - printf("%sx%x\n", - "aha: U/OVRUN on scsi command x%x\n", - cmd); - gimmeabreak(); - } - } - goto allok; - case AHA_HST_BAD_DISCONN: - printf("aha: bad disconnect\n"); - tgt->done = SCSI_RET_ABORTED; - break; - case AHA_HST_BAD_PHASE_SEQ: - /* we'll get an interrupt soon */ - printf("aha: bad PHASE sequencing\n"); - tgt->done = SCSI_RET_ABORTED; - break; - case AHA_HST_BAD_OPCODE: /* fall through */ - case AHA_HST_BAD_PARAM: -printf("aha: BADCCB\n");gimmeabreak(); - tgt->done = SCSI_RET_RETRY; - break; - case AHA_HST_BAD_LINK_LUN: /* these should not happen */ - case AHA_HST_INVALID_TDIR: - case AHA_HST_DUPLICATED_CCB: - printf("aha: bad hstatus (x%x)\n", rccb->ccb.ccb_hstatus); - tgt->done = SCSI_RET_ABORTED; - break; - } - - LOG(8,"end"); - - simple_lock(&aha->aha_lock); - if (aha->wd.nactive-- == 1) - aha->wd.watchdog_state = SCSI_WD_INACTIVE; - simple_unlock(&aha->aha_lock); - - if (tgt->ior) { - LOG(0xA,"ops->restart"); - (*tgt->dev_ops->restart)( tgt, TRUE); - } - - return FALSE; -} - -/* - * The bus was reset - */ -aha_bus_reset(aha) - register aha_softc_t aha; -{ - register port = aha->port; - - LOG(0x1d,"bus_reset"); - - /* - * Clear bus descriptor - */ - aha->wd.nactive = 0; - aha_reset(port, TRUE); - aha_init(aha); - - printf("aha: (%d) bus reset ", ++aha->wd.reset_count); - delay(scsi_delay_after_reset); /* some targets take long to reset */ - - if (aha->sc == 0) /* sanity */ - return; - - scsi_bus_was_reset(aha->sc); -} - -/* - * Watchdog - * - * We know that some (name withdrawn) disks get - * stuck in the middle of dma phases... - */ -aha_reset_scsibus(aha) - register aha_softc_t aha; -{ - register target_info_t *tgt; - register port = aha->port; - register int i; - - for (i = 0; i < AHA_NCCB; i++) { - tgt = aha->aha_ccbs[i].active_target; - if (/*scsi_debug &&*/ tgt) - printf("Target %d was active, cmd x%x in x%x out x%x\n", - tgt->target_id, tgt->cur_cmd, - tgt->transient_state.in_count, - tgt->transient_state.out_count); - } - aha_reset(port, FALSE); - delay(35); - /* no interrupt will come */ - aha_bus_reset(aha); -} - -/* - * Utilities - */ - -/* - * Send a command to the board along with some - * optional parameters, optionally receive the - * results at command completion, returns how - * many bytes we did NOT get back. - */ -aha_command(port, cmd, outp, outc, inp, inc, clear_interrupt) - unsigned char *outp, *inp; -{ - register unsigned char st; - boolean_t failed = TRUE; - - do { - st = inb(AHA_STATUS_PORT(port)); - } while (st & AHA_CSR_DATAO_FULL); - - /* Output command and any data */ - outb(AHA_COMMAND_PORT(port), cmd); - while (outc--) { - do { - st = inb(AHA_STATUS_PORT(port)); - if (st & AHA_CSR_CMD_ERR) goto out; - } while (st & AHA_CSR_DATAO_FULL); - - outb(AHA_COMMAND_PORT(port), *outp++); - } - - /* get any data */ - while (inc--) { - do { - st = inb(AHA_STATUS_PORT(port)); - if (st & AHA_CSR_CMD_ERR) goto out; - } while ((st & AHA_CSR_DATAI_FULL) == 0); - - *inp++ = inb(AHA_DATA_PORT(port)); - } - ++inc; - failed = FALSE; - - /* wait command complete */ - if (clear_interrupt) do { - delay(1); - st = inb(AHA_INTR_PORT(port)); - } while ((st & AHA_INTR_DONE) == 0); - -out: - if (clear_interrupt) - outb(AHA_CONTROL_PORT(port), AHA_CTL_INTR_CLR); - if (failed) - printf("aha_command: error on (%x %x %x %x %x %x), status %x\n", - port, cmd, outp, outc, inp, inc, st); - return inc; -} - -#include <vm/vm_kern.h> - -/* - * Allocate dynamically segment lists to - * targets (for scatter/gather) - * Its a max of 17*6=102 bytes per target. - */ -vm_offset_t aha_seglist_next, aha_seglist_end; - -aha_alloc_segment_list(tgt) - target_info_t *tgt; -{ -#define ALLOC_SIZE (AHA_MAX_SEGLIST * sizeof(aha_seglist_t)) - -/* XXX locking */ - if ((aha_seglist_next + ALLOC_SIZE) > aha_seglist_end) { - (void) kmem_alloc_wired(kernel_map, &aha_seglist_next, PAGE_SIZE); - aha_seglist_end = aha_seglist_next + PAGE_SIZE; - } - tgt->dma_ptr = (char *)aha_seglist_next; - aha_seglist_next += ALLOC_SIZE; -/* XXX locking */ -} - -#endif /* NAHA > 0 */ - diff --git a/scsi/adapters/scsi_aha17_hdw.c b/scsi/adapters/scsi_aha17_hdw.c deleted file mode 100644 index d8afe6a..0000000 --- a/scsi/adapters/scsi_aha17_hdw.c +++ /dev/null @@ -1,1371 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1993 Carnegie Mellon University - * Copyright (c) 1993 University of Dublin - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and the following permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON AND THE UNIVERSITY OF DUBLIN ALLOW FREE USE OF - * THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON AND THE - * UNIVERSITY OF DUBLIN DISCLAIM ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Support for AHA-174x in enhanced mode. Dominic Herity (dherity@cs.tcd.ie) - * Will refer to "Adaptec AHA-1740A/1742A/1744 Technical Reference Manual" - * page x-y as TRMx-y in comments below. - */ - -#include <eaha.h> -#if NEAHA > 0 - -#define db_printf printf - -#include <cpus.h> -#include <platforms.h> -#include <aha.h> - -#ifdef OSF -#include <eisa.h> -#else -#include <i386at/eisa.h> -#endif - -#include <mach/std_types.h> -#include <sys/types.h> -#include <chips/busses.h> -#include <scsi/compat_30.h> - -#include <scsi/scsi.h> -#include <scsi/scsi2.h> -#include <scsi/scsi_defs.h> - -#include <scsi/adapters/scsi_aha15.h> -#include <vm/vm_kern.h> - -#ifdef AT386 -#define MACHINE_PGBYTES I386_PGBYTES -#define MAPPABLE 0 -#define gimmeabreak() asm("int3") - - -#include <i386/pio.h> /* inlining of outb and inb */ -#ifdef OSF -#include <machine/mp/mp.h> -#endif -#endif /*AT386*/ - -#ifdef CBUS -#include <cbus/cbus.h> -#endif - - -#ifndef MACHINE_PGBYTES /* cross compile check */ -#define MACHINE_PGBYTES 0x1000 -#define MAPPABLE 1 -#define gimmeabreak() Debugger("gimmeabreak"); -#endif - -int eaha_probe(), scsi_slave(), eaha_go(), eaha_intr(); -void scsi_attach(); - -vm_offset_t eaha_std[NEAHA] = { 0 }; -struct bus_device *eaha_dinfo[NEAHA*8]; -struct bus_ctlr *eaha_minfo[NEAHA]; -struct bus_driver eaha_driver = - { eaha_probe, scsi_slave, scsi_attach, eaha_go, eaha_std, "rz", - eaha_dinfo, "eahac", eaha_minfo, BUS_INTR_B4_PROBE}; - - -#define TRACE -#ifdef TRACE - -#define LOGSIZE 256 -int eaha_logpt; -char eaha_log[LOGSIZE]; - -#define MAXLOG_VALUE 0x1e -struct { - char *name; - unsigned int count; -} logtbl[MAXLOG_VALUE]; - -static LOG( - int e, - char *f) -{ - eaha_log[eaha_logpt++] = (e); - if (eaha_logpt == LOGSIZE) eaha_logpt = 0; - if ((e) < MAXLOG_VALUE) { - logtbl[(e)].name = (f); - logtbl[(e)].count++; - } -} - -eaha_print_log( - int skip) -{ - register int i, j; - register unsigned char c; - - for (i = 0, j = eaha_logpt; i < LOGSIZE; i++) { - c = eaha_log[j]; - if (++j == LOGSIZE) j = 0; - if (skip-- > 0) - continue; - if (c < MAXLOG_VALUE) - db_printf(" %s", logtbl[c].name); - else - db_printf("-%x", c & 0x7f); - } - return 0; -} - -eaha_print_stat() -{ - register int i; - register char *p; - for (i = 0; i < MAXLOG_VALUE; i++) { - if (p = logtbl[i].name) - printf("%d %s\n", logtbl[i].count, p); - } -} - -#else /*TRACE*/ -#define LOG(e,f) -#define LOGSIZE -#endif /*TRACE*/ - -#ifdef DEBUG -#define ASSERT(x) { if (!(x)) gimmeabreak() ; } -#define MARK() gimmeabreak() -#else -#define ASSERT(x) -#define MARK() -#endif - -/* - * Notes : - * - * do each host command TRM6-4 - * find targets in probe - * disable SCSI writes - * matching port with structs, eaha_go with port, eaha_intr with port - * - */ - -/* eaha registers. See TRM4-11..23. dph */ - -#define HID0(z) ((z)+0xC80) -#define HID1(z) ((z)+0xC81) -#define HID2(z) ((z)+0xC82) -#define HID3(z) ((z)+0xC83) -#define EBCTRL(z) ((z)+0xC84) -#define PORTADDR(z) ((z)+0xCC0) -#define BIOSADDR(z) ((z)+0xCC1) -#define INTDEF(z) ((z)+0xCC2) -#define SCSIDEF(z) ((z)+0xCC3) -#define MBOXOUT0(z) ((z)+0xCD0) -#define MBOXOUT1(z) ((z)+0xCD1) -#define MBOXOUT2(z) ((z)+0xCD2) -#define MBOXOUT3(z) ((z)+0xCD3) -#define MBOXIN0(z) ((z)+0xCD8) -#define MBOXIN1(z) ((z)+0xCD9) -#define MBOXIN2(z) ((z)+0xCDA) -#define MBOXIN3(z) ((z)+0xCDB) -#define ATTN(z) ((z)+0xCD4) -#define G2CNTRL(z) ((z)+0xCD5) -#define G2INTST(z) ((z)+0xCD6) -#define G2STAT(z) ((z)+0xCD7) -#define G2STAT2(z) ((z)+0xCDC) - -/* - * Enhanced mode data structures: ring, enhanced ccbs, a per target buffer - */ - -#define SCSI_TARGETS 8 /* Allow for SCSI-2 */ - - -/* Extended Command Control Block Format. See TRM6-3..12. */ - -typedef struct { - unsigned short command ; -# define EAHA_CMD_NOP 0 -# define EAHA_CMD_INIT_CMD 1 -# define EAHA_CMD_DIAG 5 -# define EAHA_CMD_INIT_SCSI 6 -# define EAHA_CMD_READ_SENS 8 -# define EAHA_CMD_DOWNLOAD 9 -# define EAHA_CMD_HOST_INQ 0x0a -# define EAHA_CMD_TARG_CMD 0x10 - - /* - * It appears to be customary to tackle the endian-ness of - * bit fields as follows, so I won't deviate. However, nothing in - * K&R implies that bit fields are implemented so that the fields - * of an unsigned char are allocated lsb first. Indeed, K&R _warns_ - * _against_ using bit fields to describe storage allocation. - * This issue is separate from endian-ness. dph - * And this is exactly the reason macros are used. If your compiler - * is weird just override the macros and we will all be happy. af - */ - BITFIELD_3(unsigned char, - cne:1, - xxx0:6, - di:1) ; - BITFIELD_7(unsigned char, - xxx1:2, - ses:1, - xxx2:1, - sg:1, - xxx3:1, - dsb:1, - ars:1) ; - - BITFIELD_5(unsigned char, - lun:3, - tag:1, - tt:2, - nd:1, - xxx4:1) ; - BITFIELD_7(unsigned char, - dat:1, - dir:1, - st:1, - chk:1, - xxx5:2, - rec:1, - nbr:1) ; - - unsigned short xxx6 ; - - vm_offset_t scather ; /* scatter/gather */ - unsigned scathlen ; - vm_offset_t status ; - vm_offset_t chain ; - int xxx7 ; - - vm_offset_t sense_p ; - unsigned char sense_len ; - unsigned char cdb_len ; - unsigned short checksum ; - scsi_command_group_5 cdb ; - unsigned char buffer[256] ; /* space for data returned. */ - -} eccb ; - -#define NTARGETS (8) -#define NECCBS (NTARGETS+2) /* Targets + 2 to allow for temporaries. */ - /* Can be up to 64 (TRM6-2), but that entails lots of bss usage */ - -typedef struct { /* Status Block Format. See TRM6-13..19. */ - BITFIELD_8(unsigned char, - don:1, - du:1, - xxx0:1, - qf:1, - sc:1, - dover:1, - ch:1, - inti:1) ; - BITFIELD_8(unsigned char, - asa:1, /* Error in TRM6-15..16 says both asa and sns */ - sns:1, /* bit 9. Bits 8 and 10 are not mentioned. */ - xxx1:1, - ini:1, - me:1, - xxx2:1, - eca:1, - xxx3:1) ; - - unsigned char ha_status ; -# define HA_STATUS_SUCCESS 0x00 -# define HA_STATUS_HOST_ABORTED 0x04 -# define HA_STATUS_ADP_ABORTED 0x05 -# define HA_STATUS_NO_FIRM 0x08 -# define HA_STATUS_NOT_TARGET 0x0a -# define HA_STATUS_SEL_TIMEOUT 0x11 -# define HA_STATUS_OVRUN 0x12 -# define HA_STATUS_BUS_FREE 0x13 -# define HA_STATUS_PHASE_ERROR 0x14 -# define HA_STATUS_BAD_OPCODE 0x16 -# define HA_STATUS_INVALID_LINK 0x17 -# define HA_STATUS_BAD_CBLOCK 0x18 -# define HA_STATUS_DUP_CBLOCK 0x19 -# define HA_STATUS_BAD_SCATHER 0x1a -# define HA_STATUS_RSENSE_FAIL 0x1b -# define HA_STATUS_TAG_REJECT 0x1c -# define HA_STATUS_HARD_ERROR 0x20 -# define HA_STATUS_TARGET_NOATTN 0x21 -# define HA_STATUS_HOST_RESET 0x22 -# define HA_STATUS_OTHER_RESET 0x23 -# define HA_STATUS_PROG_BAD_SUM 0x80 - - scsi2_status_byte_t target_status ; - - unsigned residue ; - vm_offset_t residue_buffer ; - unsigned short add_stat_len ; - unsigned char sense_len ; - char xxx4[9] ; - unsigned char cdb[6] ; - -} status_block ; - -typedef struct { - vm_offset_t ptr ; - unsigned len ; -} scather_entry ; - -#define SCATHER_ENTRIES 128 /* TRM 6-11 */ - -struct erccbx { - target_info_t *active_target; - eccb _eccb; - status_block status ; - struct erccbx *next ; -} ; - -typedef struct erccbx erccb ; - -/* forward decls */ -int eaha_reset_scsibus(); -boolean_t eaha_probe_target(); - -/* - * State descriptor for this layer. There is one such structure - * per (enabled) board - */ -typedef struct { - watchdog_t wd; - decl_simple_lock_data(, aha_lock) - int port; /* I/O port */ - - int has_sense_info [NTARGETS]; - int sense_info_lun [NTARGETS]; - /* 1742 enhanced mode will hang if target has - * sense info and host doesn't request it (TRM6-34). - * This sometimes happens in the scsi driver. - * These flags indicate when a target has sense - * info to disgorge. - * If set, eaha_go reads and discards sense info - * before running any command except request sense. - * dph - */ - - scsi_softc_t *sc; /* HBA-indep info */ - - erccb _erccbs[NECCBS] ; /* mailboxes */ - erccb *toperccb ; - - /* This chicanery is for mapping back the phys address - of a CCB (which we get in an MBI) to its virtual */ - /* [we could use phystokv(), but it isn't standard] */ - vm_offset_t I_hold_my_phys_address; - - char host_inquiry_data[256] ; /* Check out ../scsi2.h */ - -} eaha_softc ; - -eaha_softc eaha_softc_data[NEAHA]; - -typedef eaha_softc *eaha_softc_t; - -eaha_softc_t eaha_softc_pool[NEAHA]; - -int eaha_quiet ; - -erccb *erccb_alloc( - eaha_softc *eaha) -{ - erccb *e ; - int x ; - - do { - while (eaha->toperccb == 0) ;/* Shouldn't be often or long, */ - /* BUT should use a semaphore */ - x = splbio() ; - e = eaha->toperccb ; - if (e == 0) - splx(x) ; - } while (!e) ; - eaha->toperccb = e->next ; - splx(x) ; - bzero(e,sizeof(*e)) ; - e->_eccb.status = kvtophys((vm_offset_t)&e->status) ; - return e ; -} - -void erccb_free( - eaha_softc *eaha, - erccb *e) -{ - int x ; - ASSERT ( e >= eaha->_erccbs && e < eaha->_erccbs+NECCBS) ; - x = splbio() ; - e->next = eaha->toperccb ; - eaha->toperccb = e ; - splx(x) ; -} - -void eaha_mboxout( - int port, - vm_offset_t phys) -{ - outb(MBOXOUT0(port),phys) ; - outb(MBOXOUT1(port),phys>>8) ; - outb(MBOXOUT2(port),phys>>16) ; - outb(MBOXOUT3(port),phys>>24) ; -} - -void eaha_command( /* start a command */ - int port, - erccb *_erccb) -{ - int s ; - vm_offset_t phys = kvtophys((vm_offset_t) &_erccb->_eccb) ; - while ((inb(G2STAT(port)) & 0x04)==0); /*While MBO busy. TRM6-1 */ - s = splbio() ; - eaha_mboxout(port,phys) ; - while (inb(G2STAT(port)) & 1) ; /* While adapter busy. TRM6-2 */ - outb(ATTN(port),0x40 | _erccb->active_target->target_id) ; /* TRM6-20 */ - /* (Should use target id for intitiator command) */ - splx(s) ; -} - -eaha_reset( - eaha_softc_t eaha, - boolean_t quick) -{ - /* - * Reset board and wait till done - */ - unsigned st ; - int target_id ; - int port = eaha->port ; - - /* Reset adapter, maybe with SCSIbus */ - eaha_mboxout(port, quick ? 0x00080080 : 0x00000080 ) ; /* TRM 6-43..45 */ - outb(ATTN(port), 0x10 | inb(SCSIDEF(port)) & 0x0f) ; - outb(G2CNTRL(port),0x20) ; /* TRM 4-22 */ - - do { - st = inb(G2INTST(port)) >> 4 ; - } while (st == 0) ; - /* TRM 4-22 implies that 1 should not be returned in G2INTST, but - in practise, it is. So this code takes 0 to mean non-completion. */ - - for (target_id = 0 ; target_id < NTARGETS; target_id++) - eaha->has_sense_info[target_id] = FALSE ; - -} - -void eaha_init( - eaha_softc_t eaha) -{ - /* Do nothing - I guess */ -} - -void eaha_bus_reset( - eaha_softc_t eaha) - -{ - LOG(0x1d,"bus_reset"); - - /* - * Clear bus descriptor - */ - eaha->wd.nactive = 0; - eaha_reset(eaha, TRUE); - eaha_init(eaha); - - printf("eaha: (%d) bus reset ", ++eaha->wd.reset_count); - delay(scsi_delay_after_reset); /* some targets take long to reset */ - - if (eaha->sc == 0) /* sanity */ - return; - - scsi_bus_was_reset(eaha->sc); -} - -#ifdef notdef - /* functions added to complete 1742 support, but not used. Untested. */ - - void eaha_download(port, data, len) - int port ; - char *data ; - unsigned len ; - { - /* 1744 firmware download. Not implemented. TRM6-21 */ - } - - void eaha_initscsi(data, len) - char *data ; - unsigned len ; - { - /* initialize SCSI subsystem. Presume BIOS does it. - Not implemented. TRM6-23 */ - } - - void eaha_noop() - { - /* Not implemented. TRM6-27 */ - } - - erccb *eaha_host_adapter_inquiry(eaha) /* Returns a promise */ - eaha_softc *eaha ; /* TRM6-31..33 */ - { - erccb *_erccb = erccb_alloc(eaha) ; - _erccb->_eccb.scather = (vm_offset_t) kvtophys(eaha->host_inquiry_data) ; - _erccb->_eccb.scathlen = sizeof(eaha->host_inquiry_data) ; - _erccb->_eccb.ses = 1 ; - _erccb->_eccb.command = EAHA_CMD_HOST_INQ ; - eaha_command(eaha->port,_erccb->_eccb,0) ; /* Is scsi_id used */ - return _erccb ; - } - - erccb *eaha_read_sense_info(eaha, target, lun) /* TRM 6-33..35 */ - eaha_softc *eaha ; - unsigned target, lun ; - { /* Don't think we need this because its done in scsi_alldevs.c */ - #ifdef notdef - erccb *_erccb = erccb_alloc(eaha) ; - _erccb->_eccb.command = EAHA_CMD_READ_SENS ; - _erccb->_eccb.lun = lun ; - eaha_command(eaha->port,_erccb->_eccb, target) ;/*Wrong # args*/ - return _erccb ; - #else - return 0 ; - #endif - } - - void eaha_diagnostic(eaha) - eaha_softc *eaha ; - { - /* Not implemented. TRM6-36..37 */ - } - - erccb *eaha_target_cmd(eaha, target, lun, data, len) /* TRM6-38..39 */ - eaha_softc *eaha ; - unsigned target, lun ; - char *data ; - unsigned len ; - { - erccb *_erccb = erccb_alloc(eaha) ; - _erccb->_eccb.command = EAHA_CMD_TARG_CMD ; - _erccb->_eccb.lun = lun ; - eaha_command(eaha->port,_erccb->_eccb,target);/*Wrong # args*/ - return _erccb ; - } - - erccb *eaha_init_cmd(port) /* SHOULD RETURN TOKEN. i.e. ptr to eccb */ - /* Need list of free eccbs */ - { /* to be continued,. possibly. */ - } - -#endif /* notdef */ - -target_info_t * -eaha_tgt_alloc( - eaha_softc_t eaha, - int id, - target_info_t *tgt) -{ - erccb *_erccb; - - if (tgt == 0) - tgt = scsi_slave_alloc(eaha - eaha_softc_data, id, eaha); - - _erccb = erccb_alloc(eaha) ; /* This is very dodgy */ - tgt->cmd_ptr = (char *)& _erccb->_eccb.cdb ; - tgt->dma_ptr = 0; - return tgt; -} - - -struct { - scsi_sense_data_t sns ; - unsigned char extra - [254-sizeof(scsi_sense_data_t)] ; -} eaha_xsns [NTARGETS] ;/*must be bss to be contiguous*/ - - -/* Enhanced adapter probe routine */ - -eaha_probe( - register int port, - struct bus_ctlr *ui) -{ - int unit = ui->unit; - eaha_softc_t eaha = &eaha_softc_data[unit] ; - int target_id ; - scsi_softc_t *sc ; - int s; - boolean_t did_banner = FALSE ; - struct aha_devs installed; - unsigned char my_scsi_id, my_interrupt ; - - if (unit >= NEAHA) - return(0); - - /* No interrupts yet */ - s = splbio(); - - /* - * Detect prescence of 174x in enhanced mode. Ignore HID2 and HID3 - * on the assumption that compatibility will be preserved. dph - */ - if (inb(HID0(port)) != 0x04 || inb(HID1(port)) != 0x90 || - (inb(PORTADDR(port)) & 0x80) != 0x80) { - splx(s); - return 0 ; - } - - /* Issue RESET in case this is a reboot */ - - outb(EBCTRL(port),0x04) ; /* Disable board. TRM4-12 */ - outb(PORTADDR(port),0x80) ; /* Disable standard mode ports. TRM4-13. */ - my_interrupt = inb(INTDEF(port)) & 0x07 ; - outb(INTDEF(port), my_interrupt | 0x00) ; - /* Disable interrupts. TRM4-15 */ - my_scsi_id = inb(SCSIDEF(port)) & 0x0f ; - outb(SCSIDEF(port), my_scsi_id | 0x10) ; - /* Force SCSI reset on hard reset. TRM4-16 */ - outb(G2CNTRL(port),0xe0) ; /* Reset board, clear interrupt */ - /* and set 'host ready'. */ - delay(10*10) ; /* HRST must remain set for 10us. TRM4-22 */ - /* (I don't believe the delay loop is slow enough.) */ - outb(G2CNTRL(port),0x60);/*Un-reset board, set 'host ready'. TRM4-22*/ - - printf("Adaptec 1740A/1742A/1744 enhanced mode\n"); - - /* Get host inquiry data */ - - eaha_softc_pool[unit] = eaha ; - bzero(eaha,sizeof(*eaha)) ; - eaha->port = port ; - - sc = scsi_master_alloc(unit, eaha) ; - eaha->sc = sc ; - sc->go = eaha_go ; - sc->watchdog = scsi_watchdog ; - sc->probe = eaha_probe_target ; - eaha->wd.reset = eaha_reset_scsibus ; - sc->max_dma_data = -1 ; /* Lets be optimistic */ - sc->initiator_id = my_scsi_id ; - eaha_reset(eaha,TRUE) ; - eaha->I_hold_my_phys_address = - kvtophys((vm_offset_t)&eaha->I_hold_my_phys_address) ; - { - erccb *e ; - eaha->toperccb = eaha->_erccbs ; - for (e=eaha->_erccbs; e < eaha->_erccbs+NECCBS; e++) { - e->next = e+1 ; - e->_eccb.status = - kvtophys((vm_offset_t) &e->status) ; - } - eaha->_erccbs[NECCBS-1].next = 0 ; - - } - - ui->sysdep1 = my_interrupt + 9 ; - take_ctlr_irq(ui) ; - - printf("%s%d: [port 0x%x intr ch %d] my SCSI id is %d", - ui->name, unit, port, my_interrupt + 9, my_scsi_id) ; - - outb(INTDEF(port), my_interrupt | 0x10) ; - /* Enable interrupts. TRM4-15 */ - outb(EBCTRL(port),0x01) ; /* Enable board. TRM4-12 */ - - { target_info_t *t = eaha_tgt_alloc(eaha, my_scsi_id, 0) ; - /* Haven't enabled target mode a la standard mode, because */ - /* it doesn't seem to be necessary. */ - sccpu_new_initiator(t, t) ; - } - - /* Find targets, incl. ourselves. */ - - for (target_id=0; target_id < SCSI_TARGETS; target_id++) - if (target_id != sc->initiator_id) { - scsi_cmd_test_unit_ready_t *cmd; - erccb *_erccb = erccb_alloc(eaha) ; - unsigned attempts = 0 ; -#define MAX_ATTEMPTS 2 - target_info_t temp_targ ; - - temp_targ.ior = 0 ; - temp_targ.hw_state = (char *) eaha ; - temp_targ.cmd_ptr = (char *) &_erccb->_eccb.cdb ; - temp_targ.target_id = target_id ; - temp_targ.lun = 0 ; - temp_targ.cur_cmd = SCSI_CMD_TEST_UNIT_READY; - - cmd = (scsi_cmd_test_unit_ready_t *) temp_targ.cmd_ptr; - - do { - cmd->scsi_cmd_code = SCSI_CMD_TEST_UNIT_READY; - cmd->scsi_cmd_lun_and_lba1 = 0; /*assume 1 lun?*/ - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_ss_flags = 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - eaha_go( &temp_targ, - sizeof(scsi_cmd_test_unit_ready_t),0,0); - /* ints disabled, so call isr yourself. */ - while (temp_targ.done == SCSI_RET_IN_PROGRESS) - if (inb(G2STAT(eaha->port)) & 0x02) { - eaha_quiet = 1 ; - eaha_intr(unit) ; - eaha_quiet = 0 ; - } - if (temp_targ.done == SCSI_RET_NEED_SENSE) { - /* MUST get sense info : TRM6-34 */ - if (eaha_retrieve_sense_info( - eaha, temp_targ.target_id, - temp_targ.lun) && - attempts == MAX_ATTEMPTS-1) { - - printf( - "\nTarget %d Check Condition : " - ,temp_targ.target_id) ; - scsi_print_sense_data(&eaha_xsns - [temp_targ.target_id]); - printf("\n") ; - } - } - } while (temp_targ.done != SCSI_RET_SUCCESS && - temp_targ.done != SCSI_RET_ABORTED && - ++attempts < MAX_ATTEMPTS) ; - - /* - * Recognize target which is present, whether or not - * it is ready, e.g. drive with removable media. - */ - if (temp_targ.done == SCSI_RET_SUCCESS || - temp_targ.done == SCSI_RET_NEED_SENSE && - _erccb->status.target_status.bits != 0) { /* Eureka */ - installed.tgt_luns[target_id]=1;/*Assume 1 lun?*/ - printf(", %s%d", - did_banner++ ? "" : "target(s) at ", - target_id); - - erccb_free(eaha, _erccb) ; - - /* Normally, only LUN 0 */ - if (installed.tgt_luns[target_id] != 1) - printf("(%x)", installed.tgt_luns[target_id]); - /* - * Found a target - */ - (void) eaha_tgt_alloc(eaha, target_id, 0); - /* Why discard ? */ - } else - installed.tgt_luns[target_id]=0; - } - - printf(".\n") ; - splx(s); - return 1 ; -} - -int eaha_retrieve_sense_info ( - eaha_softc_t eaha, - int tid, - int lun) -{ - int result ; - int s ; - target_info_t dummy_target ; /* Keeps eaha_command() happy. HACK */ - erccb *_erccb1 = erccb_alloc(eaha) ; - - _erccb1->active_target = &dummy_target ; - dummy_target.target_id = tid ; - _erccb1->_eccb.command = - EAHA_CMD_READ_SENS ; - _erccb1->_eccb.lun = lun ; - _erccb1->_eccb.sense_p = kvtophys((vm_offset_t) &eaha_xsns [tid]); - _erccb1->_eccb.sense_len = sizeof(eaha_xsns [tid]); - _erccb1->_eccb.ses = 1 ; - s = splbio() ; - eaha_command(eaha->port,_erccb1) ; - while ((inb(G2STAT(eaha->port)) & 0x02) == 0) ; - outb(G2CNTRL(eaha->port),0x40);/* Clear int */ - splx(s) ; - result = _erccb1->status.target_status.bits != 0 ; - erccb_free(eaha,_erccb1) ; - return result ; -} - -/* - * Start a SCSI command on a target (enhanced mode) - */ -eaha_go( - target_info_t *tgt, - int cmd_count, - int in_count, - boolean_t cmd_only)/*lint: unused*/ -{ - eaha_softc_t eaha; - int s; - erccb *_erccb; - int len; - vm_offset_t virt; - int tid = tgt->target_id ; - -#ifdef CBUS - at386_io_lock_state(); -#endif - LOG(1,"go"); - -#ifdef CBUS - at386_io_lock(MP_DEV_WAIT); -#endif - eaha = (eaha_softc_t)tgt->hw_state; - - if(eaha->has_sense_info[tid]) { - (void) eaha_retrieve_sense_info - (eaha, tid, eaha->sense_info_lun[tid]) ; - eaha->has_sense_info[tid] = FALSE ; - if (tgt->cur_cmd == SCSI_CMD_REQUEST_SENSE) { - bcopy(&eaha_xsns[tid],tgt->cmd_ptr,in_count) ; - tgt->done = SCSI_RET_SUCCESS; - tgt->transient_state.cmd_count = cmd_count; - tgt->transient_state.out_count = 0; - tgt->transient_state.in_count = in_count; - /* Fake up interrupt */ - /* Highlights from eaha_initiator_intr(), */ - /* ignoring errors */ - if (tgt->ior) - (*tgt->dev_ops->restart)( tgt, TRUE); -#ifdef CBUS - at386_io_unlock(); -#endif - return ; - } - } - -/* XXX delay the handling of the ccb till later */ - _erccb = (erccb *) - ((unsigned)tgt->cmd_ptr - (unsigned) &((erccb *) 0)->_eccb.cdb); - /* Tell *rccb about target, eg. id ? */ - _erccb->active_target = tgt; - - /* - * We can do real DMA. - */ -/* tgt->transient_state.copy_count = 0; unused */ -/* tgt->transient_state.dma_offset = 0; unused */ - - tgt->transient_state.cmd_count = cmd_count; - - if ((tgt->cur_cmd == SCSI_CMD_WRITE) || - (tgt->cur_cmd == SCSI_CMD_LONG_WRITE)){ - io_req_t ior = tgt->ior; - register int len = ior->io_count; - - tgt->transient_state.out_count = len; - - /* How do we avoid leaks here ? Trust the board - will do zero-padding, for now. XXX CHECKME */ -#if 0 - if (len < tgt->block_size) { - bzero(to + len, tgt->block_size - len); - len = tgt->block_size; - tgt->transient_state.out_count = len; - } -#endif - } else { - tgt->transient_state.out_count = 0; - } - - /* See above for in_count < block_size */ - tgt->transient_state.in_count = in_count; - - /* - * Setup CCB state - */ - tgt->done = SCSI_RET_IN_PROGRESS; - - switch (tgt->cur_cmd) { - case SCSI_CMD_READ: - case SCSI_CMD_LONG_READ: - LOG(9,"readop"); - virt = (vm_offset_t)tgt->ior->io_data; - len = tgt->transient_state.in_count; - break; - case SCSI_CMD_WRITE: - case SCSI_CMD_LONG_WRITE: - LOG(0x1a,"writeop"); - virt = (vm_offset_t)tgt->ior->io_data; - len = tgt->transient_state.out_count; - break; - case SCSI_CMD_INQUIRY: - case SCSI_CMD_REQUEST_SENSE: - case SCSI_CMD_MODE_SENSE: - case SCSI_CMD_RECEIVE_DIAG_RESULTS: - case SCSI_CMD_READ_CAPACITY: - case SCSI_CMD_READ_BLOCK_LIMITS: - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - virt = (vm_offset_t)tgt->cmd_ptr; - len = tgt->transient_state.in_count; - break; - case SCSI_CMD_MODE_SELECT: - case SCSI_CMD_REASSIGN_BLOCKS: - case SCSI_CMD_FORMAT_UNIT: - tgt->transient_state.cmd_count = sizeof(scsi_command_group_0); - len = - tgt->transient_state.out_count = cmd_count - sizeof(scsi_command_group_0); - virt = (vm_offset_t)tgt->cmd_ptr+sizeof(scsi_command_group_0); - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - default: - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - virt = 0; - len = 0; - } - - eaha_prepare_rccb(tgt, _erccb, virt, len); - - _erccb->_eccb.lun = tgt->lun; - - /* - * XXX here and everywhere, locks! - */ - s = splbio(); - - simple_lock(&eaha->aha_lock); - if (eaha->wd.nactive++ == 0) - eaha->wd.watchdog_state = SCSI_WD_ACTIVE; - simple_unlock(&eaha->aha_lock); - - LOG(3,"enqueue"); - - eaha_command(eaha->port, _erccb) ; - - splx(s); -#ifdef CBUS - at386_io_unlock(); -#endif -} - -eaha_prepare_rccb( - target_info_t *tgt, - erccb *_erccb, - vm_offset_t virt, - vm_size_t len) -{ - _erccb->_eccb.cdb_len = tgt->transient_state.cmd_count; - - _erccb->_eccb.command = EAHA_CMD_INIT_CMD;/* default common case */ - - if (virt == 0) { - /* no xfers */ - _erccb->_eccb.scather = 0 ; - _erccb->_eccb.scathlen = 0 ; - _erccb->_eccb.sg = 0 ; - } else { - /* messy xfer */ - scather_entry *seglist; - vm_size_t l1, off; - - _erccb->_eccb.sg = 1 ; - - if (tgt->dma_ptr == 0) - eaha_alloc_segment_list(tgt); - seglist = (scather_entry *) tgt->dma_ptr; - - _erccb->_eccb.scather = kvtophys((vm_offset_t) seglist); - - l1 = MACHINE_PGBYTES - (virt & (MACHINE_PGBYTES - 1)); - if (l1 > len) - l1 = len ; - - off = 1;/* now #pages */ - while (1) { - seglist->ptr = kvtophys(virt) ; - seglist->len = l1 ; - seglist++; - - if (len <= l1) - break ; - len-= l1 ; - virt += l1; off++; - - l1 = (len > MACHINE_PGBYTES) ? MACHINE_PGBYTES : len; - } - _erccb->_eccb.scathlen = off * sizeof(*seglist); - } -} - -/* - * Allocate dynamically segment lists to - * targets (for scatter/gather) - */ -vm_offset_t eaha_seglist_next = 0, eaha_seglist_end = 0 ; -#define EALLOC_SIZE (SCATHER_ENTRIES * sizeof(scather_entry)) - -eaha_alloc_segment_list( - target_info_t *tgt) -{ - -/* XXX locking */ -/* ? Can't spl() for unknown duration */ - if ((eaha_seglist_next + EALLOC_SIZE) > eaha_seglist_end) { - (void)kmem_alloc_wired(kernel_map,&eaha_seglist_next,PAGE_SIZE); - eaha_seglist_end = eaha_seglist_next + PAGE_SIZE; - } - tgt->dma_ptr = (char *)eaha_seglist_next; - eaha_seglist_next += EALLOC_SIZE; -/* XXX locking */ -} - -/* - * - * shameless copy from above - */ -eaha_reset_scsibus( - register eaha_softc_t eaha) -{ - register target_info_t *tgt; - register port = eaha->port; - register int i; - - for (i = 0; i < NECCBS; i++) { - tgt = eaha->_erccbs[i].active_target; - if (/*scsi_debug &&*/ tgt) - printf("Target %d was active, cmd x%x in x%x out x%x\n", - tgt->target_id, tgt->cur_cmd, - tgt->transient_state.in_count, - tgt->transient_state.out_count); - } - eaha_reset(eaha, FALSE); - delay(35); - /* no interrupt will come */ - eaha_bus_reset(eaha); -} - -boolean_t -eaha_probe_target( - target_info_t *tgt, - io_req_t ior) -{ - eaha_softc_t eaha = eaha_softc_pool[tgt->masterno]; - boolean_t newlywed; - - newlywed = (tgt->cmd_ptr == 0); - if (newlywed) { - /* desc was allocated afresh */ - (void) eaha_tgt_alloc(eaha,tgt->target_id, tgt); - } - - if (scsi_inquiry(tgt, SCSI_INQ_STD_DATA) == SCSI_RET_DEVICE_DOWN) - return FALSE; - - tgt->flags = TGT_ALIVE; - return TRUE; -} - - -/* - * Interrupt routine (enhanced mode) - * Take interrupts from the board - * - * Implementation: - * TBD - */ -eaha_intr( - int unit) -{ - register eaha_softc_t eaha; - register port; - unsigned g2intst, g2stat, g2stat2 ; - vm_offset_t mbi ; - erccb *_erccb ; - status_block *status ; - -#if MAPPABLE - extern boolean_t rz_use_mapped_interface; - - if (rz_use_mapped_interface) { - EAHA_intr(unit); - return ; - } -#endif /*MAPPABLE*/ - - eaha = eaha_softc_pool[unit]; - port = eaha->port; - - LOG(5,"\n\tintr"); -gotintr: - /* collect ephemeral information */ - - g2intst = inb(G2INTST(port)) ; /* See TRM4-22..23 */ - g2stat = inb(G2STAT(port)) ; /*lint:set,not used*/ - g2stat2 = inb(G2STAT2(port)) ; /*lint:set,not used*/ - mbi = (vm_offset_t) inb(MBOXIN0(port)) + (inb(MBOXIN1(port))<<8) + - (inb(MBOXIN2(port))<<16) + (inb(MBOXIN3(port))<<24) ; - - /* we got an interrupt allright */ - if (eaha->wd.nactive) - eaha->wd.watchdog_state = SCSI_WD_ACTIVE; - - outb(G2CNTRL(port),0x40) ; /* Clear EISA interrupt */ - - switch(g2intst>>4) { - case 0x07 : /* hardware error ? */ - case 0x0a : /* immediate command complete - don't expect */ - case 0x0e : /* ditto with failure */ - default : - printf( "aha%d: Bogus status (x%x) in MBI\n", - unit, mbi); - gimmeabreak() ; /* Any of above is disaster */ - break; - - case 0x0d : /* Asynchronous event TRM6-41 */ - if ((g2intst & 0x0f) == (inb(SCSIDEF(eaha->port)) & 0x0f)) - eaha_reset_scsibus(eaha) ; - else - eaha_target_intr(eaha, mbi, g2intst & 0x0f); - break; - - case 0x0c : /* ccb complete with error */ - case 0x01 : /* ccb completed with success */ - case 0x05 : /* ccb complete with success after retry */ - - _erccb = (erccb *) - ( ((vm_offset_t)&eaha->I_hold_my_phys_address) + - (mbi - eaha->I_hold_my_phys_address) - - (vm_offset_t)&(((erccb *)0)->_eccb) ) ; - /* That ain't necessary. As kernel (must be) */ - /* contiguous, only need delta to translate */ - - status = &_erccb->status ; - -#ifdef NOTDEF - if (!eaha_quiet && (!status->don || status->qf || - status->sc || status->dover || - status->ini || status->me)) { - printf("\nccb complete error G2INTST=%02X\n", - g2intst) ; - DUMP(*_erccb) ; - gimmeabreak() ; - } -#endif - - eaha_initiator_intr(eaha, _erccb); - break; - } - - /* See if more work ready */ - if (inb(G2STAT(port)) & 0x02) { - LOG(7,"\n\tre-intr"); - goto gotintr; - } -} - -/* - * The interrupt routine turns to one of these two - * functions, depending on the incoming mbi's role - */ -eaha_target_intr( - eaha_softc_t eaha, - unsigned int mbi, - unsigned int peer) -{ - target_info_t *initiator; /* this is the caller */ - target_info_t *self; /* this is us */ - int len; - - self = eaha->sc->target[eaha->sc->initiator_id]; - - initiator = eaha->sc->target[peer]; - - /* ..but initiators are not required to answer to our inquiry */ - if (initiator == 0) { - /* allocate */ - initiator = eaha_tgt_alloc(eaha, peer, 0); - - /* We do not know here wether the host was down when - we inquired, or it refused the connection. Leave - the decision on how we will talk to it to higher - level code */ - LOG(0xC, "new_initiator"); - sccpu_new_initiator(self, initiator); - /* Bug fix: was (aha->sc, self, initiator); dph */ - } - - /* The right thing to do would be build an ior - and call the self->dev_ops->strategy routine, - but we cannot allocate it at interrupt level. - Also note that we are now disconnected from the - initiator, no way to do anything else with it - but reconnect and do what it wants us to do */ - - /* obviously, this needs both spl and MP protection */ - self->dev_info.cpu.req_pending = TRUE; - self->dev_info.cpu.req_id = peer ; - self->dev_info.cpu.req_lun = (mbi>>24) & 0x07 ; - self->dev_info.cpu.req_cmd = - (mbi & 0x80000000) ? SCSI_CMD_SEND: SCSI_CMD_RECEIVE; - len = mbi & 0x00ffffff ; - - self->dev_info.cpu.req_len = len; - - LOG(0xB,"tgt-mode-restart"); - (*self->dev_ops->restart)( self, FALSE); - - /* The call above has either prepared the data, - placing an ior on self, or it handled it some - other way */ - if (self->ior == 0) - return; /* I guess we'll do it later */ - - { - erccb *_erccb ; - - _erccb = erccb_alloc(eaha) ; - _erccb->active_target = initiator; - _erccb->_eccb.command = EAHA_CMD_TARG_CMD ; - _erccb->_eccb.ses = 1 ; - _erccb->_eccb.dir = (self->cur_cmd == SCSI_CMD_SEND) ? 1 : 0 ; - - eaha_prepare_rccb(initiator, _erccb, - (vm_offset_t)self->ior->io_data, self->ior->io_count); - _erccb->_eccb.lun = initiator->lun; - - simple_lock(&eaha->aha_lock); - if (eaha->wd.nactive++ == 0) - eaha->wd.watchdog_state = SCSI_WD_ACTIVE; - simple_unlock(&eaha->aha_lock); - - eaha_command(eaha->port, _erccb); - } -} - -eaha_initiator_intr( - eaha_softc_t eaha, - erccb *_erccb) -{ - scsi2_status_byte_t status; - target_info_t *tgt; - - tgt = _erccb->active_target; - _erccb->active_target = 0; - - /* shortcut (sic!) */ - if (_erccb->status.ha_status == HA_STATUS_SUCCESS) - goto allok; - - switch (_erccb->status.ha_status) { /* TRM6-17 */ - case HA_STATUS_SUCCESS : -allok: - status = _erccb->status.target_status ; - if (status.st.scsi_status_code != SCSI_ST_GOOD) { - scsi_error(tgt, SCSI_ERR_STATUS, status.bits, 0); - tgt->done = (status.st.scsi_status_code == SCSI_ST_BUSY) ? - SCSI_RET_RETRY : SCSI_RET_NEED_SENSE; - } else - tgt->done = SCSI_RET_SUCCESS; - break; - - case HA_STATUS_SEL_TIMEOUT : - if (tgt->flags & TGT_FULLY_PROBED) - tgt->flags = 0; /* went offline */ - tgt->done = SCSI_RET_DEVICE_DOWN; - break; - - case HA_STATUS_OVRUN : - /* BUT we don't know if this is an underrun. - It is ok if we get less data than we asked - for, in a number of cases. Most boards do not - seem to generate this anyways, but some do. */ - { register int cmd = tgt->cur_cmd; - switch (cmd) { - case SCSI_CMD_INQUIRY: - case SCSI_CMD_REQUEST_SENSE: - case SCSI_CMD_RECEIVE_DIAG_RESULTS: - case SCSI_CMD_MODE_SENSE: - if (_erccb->status.du) /*Ignore underrun only*/ - break; - default: - printf("eaha: U/OVRUN on scsi command x%x\n",cmd); - gimmeabreak(); - } - } - goto allok; - case HA_STATUS_BUS_FREE : - printf("aha: bad disconnect\n"); - tgt->done = SCSI_RET_ABORTED; - break; - case HA_STATUS_PHASE_ERROR : - /* we'll get an interrupt soon */ - printf("aha: bad PHASE sequencing\n"); - tgt->done = SCSI_RET_ABORTED; - break; - case HA_STATUS_BAD_OPCODE : -printf("aha: BADCCB\n");gimmeabreak(); - tgt->done = SCSI_RET_RETRY; - break; - - case HA_STATUS_HOST_ABORTED : - case HA_STATUS_ADP_ABORTED : - case HA_STATUS_NO_FIRM : - case HA_STATUS_NOT_TARGET : - case HA_STATUS_INVALID_LINK : /* These aren't expected. */ - case HA_STATUS_BAD_CBLOCK : - case HA_STATUS_DUP_CBLOCK : - case HA_STATUS_BAD_SCATHER : - case HA_STATUS_RSENSE_FAIL : - case HA_STATUS_TAG_REJECT : - case HA_STATUS_HARD_ERROR : - case HA_STATUS_TARGET_NOATTN : - case HA_STATUS_HOST_RESET : - case HA_STATUS_OTHER_RESET : - case HA_STATUS_PROG_BAD_SUM : - default : - printf("aha: bad ha_status (x%x)\n", _erccb->status.ha_status); - tgt->done = SCSI_RET_ABORTED; - break; - } - - eaha->has_sense_info [tgt->target_id] = - (tgt->done == SCSI_RET_NEED_SENSE) ; - if (eaha->has_sense_info [tgt->target_id]) - eaha->sense_info_lun [tgt->target_id] = tgt->lun ; - - LOG(8,"end"); - - simple_lock(&eaha->aha_lock); - if (eaha->wd.nactive-- == 1) - eaha->wd.watchdog_state = SCSI_WD_INACTIVE; - simple_unlock(&eaha->aha_lock); - - if (tgt->ior) { - LOG(0xA,"ops->restart"); - (*tgt->dev_ops->restart)( tgt, TRUE); - } - - return FALSE;/*lint: Always returns FALSE. ignored. */ -} - -#endif /* NEAHA > 0 */ diff --git a/scsi/adapters/scsi_dma.h b/scsi/adapters/scsi_dma.h deleted file mode 100644 index 9401a16..0000000 --- a/scsi/adapters/scsi_dma.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS AS-IS - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_dma.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 7/91 - * - * DMA operations that an HBA driver might invoke. - * - */ - -/* - * This defines much more than usually needed, mainly - * to cover for the case of no DMA at all and/or only - * DMA from/to a specialized buffer ( which means the - * CPU has to copy data into/outof it ). - */ - -typedef struct { - opaque_t (*init)( - int dev_unit, - vm_offset_t base, - int *dma_bsizep, - boolean_t *oddbp); - - void (*new_target)( - opaque_t dma_state, - target_info_t *tgt); - - void (*map)( - opaque_t dma_state, - target_info_t *tgt); - - int (*start_cmd)( - opaque_t dma_state, - target_info_t *tgt); - - void (*end_xfer)( - opaque_t dma_state, - target_info_t *tgt, - int xferred); - - void (*end_cmd)( - opaque_t dma_state, - target_info_t *tgt, - io_req_t ior); - - int (*start_datain)( - opaque_t dma_state, - target_info_t *tgt); - - int (*start_msgin)( - opaque_t dma_state, - target_info_t *tgt); - - void (*end_msgin)( - opaque_t dma_state, - target_info_t *tgt); - - boolean_t (*start_dataout)( - opaque_t dma_state, - target_info_t *tgt, - volatile unsigned *regp, - unsigned value, - unsigned char *prefetch_count); - - int (*restart_datain_1)( - opaque_t dma_state, - target_info_t *tgt); - - int (*restart_datain_2)( - opaque_t dma_state, - target_info_t *tgt, - int xferred); - - void (*restart_datain_3)( - opaque_t dma_state, - target_info_t *tgt); - - int (*restart_dataout_1)( - opaque_t dma_state, - target_info_t *tgt); - - int (*restart_dataout_2)( - opaque_t dma_state, - target_info_t *tgt, - int xferred); - - int (*restart_dataout_3)( - opaque_t dma_state, - target_info_t *tgt, - volatile unsigned *regp); - - void (*restart_dataout_4)( - opaque_t dma_state, - target_info_t *tgt); - - boolean_t (*disconn_1)( - opaque_t dma_state, - target_info_t *tgt, - int xferred); - - boolean_t (*disconn_2)( - opaque_t dma_state, - target_info_t *tgt); - - boolean_t (*disconn_3)( - opaque_t dma_state, - target_info_t *tgt, - int xferred); - - boolean_t (*disconn_4)( - opaque_t dma_state, - target_info_t *tgt, - int xferred); - - boolean_t (*disconn_5)( - opaque_t dma_state, - target_info_t *tgt, - int xferred); - - void (*disconn_callback)( - opaque_t dma_state, - target_info_t *tgt); - -} scsi_dma_ops_t; - diff --git a/scsi/adapters/scsi_user_dma.c b/scsi/adapters/scsi_user_dma.c deleted file mode 100644 index 5fb98d6..0000000 --- a/scsi/adapters/scsi_user_dma.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ -/* - * File: scsi_user_dma.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 4/91 - * - * Mach 2.5 compat file, to handle case of DMA to user space - * [e.g. fsck and other raw device accesses] - */ - -#ifdef MACH_KERNEL -/* We do not need this in 3.0 */ -#else /*MACH_KERNEL*/ - -#include <mach/std_types.h> -#include <scsi/adapters/scsi_user_dma.h> - -#include <kern/assert.h> - -#include <vm/vm_kern.h> -#include <mach/vm_param.h> /* round_page() */ - -/* bp -> pmap */ -#include <sys/buf.h> -#include <sys/proc.h> - -/* - * Initialization, called once per device - */ -fdma_init(fdma, size) - fdma_t fdma; - vm_size_t size; -{ - vm_offset_t addr; - - size = round_page(size); - addr = kmem_alloc_pageable(kernel_map, size); - if (addr == 0) panic("fdma_init"); - - fdma->kernel_virtual = addr; - fdma->max_data = size; - fdma->user_virtual = -1; - -} - -/* - * Remap a buffer from user space to kernel space. - * Note that physio() has already validated - * and wired the user's address range. - */ -fdma_map(fdma, bp) - fdma_t fdma; - struct buf *bp; -{ - pmap_t pmap; - vm_offset_t user_addr; - vm_size_t size; - vm_offset_t kernel_addr; - vm_offset_t off; - vm_prot_t prot; - - /* - * If this is not to user space, or no data xfer is - * involved, no need to do anything. - */ - user_addr = (vm_offset_t)bp->b_un.b_addr; - if (!(bp->b_flags & B_PHYS) || (user_addr == 0)) { - fdma->user_virtual = -1; - return; - } - /* - * We are going to clobber the buffer pointer, so - * remember what it was to restore it later. - */ - fdma->user_virtual = user_addr; - - /* - * Account for initial offset into phys page - */ - off = user_addr - trunc_page(user_addr); - - /* - * Check xfer size makes sense, note how many pages we'll remap - */ - size = bp->b_bcount + off; - assert((size <= fdma->max_data)); - fdma->xfer_size_rnd = round_page(size); - - pmap = bp->b_proc->task->map->pmap; - - /* - * Use minimal protection possible - */ - prot = VM_PROT_READ; - if (bp->b_flags & B_READ) - prot |= VM_PROT_WRITE; - - /* - * Loop through all phys pages, taking them from the - * user pmap (they are wired) and inserting them into - * the kernel pmap. - */ - user_addr -= off; - kernel_addr = fdma->kernel_virtual; - bp->b_un.b_addr = (char *)kernel_addr + off; - - for (size = fdma->xfer_size_rnd; size; size -= PAGE_SIZE) { - register vm_offset_t phys; - - phys = pmap_extract(pmap, user_addr); - pmap_enter(kernel_pmap, kernel_addr, phys, prot, TRUE); - user_addr += PAGE_SIZE; - kernel_addr += PAGE_SIZE; - } -} - -/* - * Called at end of xfer, to restore the buffer - */ -fdma_unmap(fdma, bp) - fdma_t fdma; - struct buf *bp; -{ - register vm_offset_t end_addr; - - /* - * Check we actually did remap it - */ - if (fdma->user_virtual == -1) - return; - - /* - * Restore the buffer - */ - bp->b_un.b_addr = (char *)fdma->user_virtual; - fdma->user_virtual = -1; - - /* - * Eliminate the mapping, pmap module might mess up - * the pv list otherwise. Some might actually tolerate it. - */ - end_addr = fdma->kernel_virtual + fdma->xfer_size_rnd; - pmap_remove(kernel_pmap, fdma->kernel_virtual, end_addr); - -} - -#endif /*MACH_KERNEL*/ diff --git a/scsi/adapters/scsi_user_dma.h b/scsi/adapters/scsi_user_dma.h deleted file mode 100644 index ff2682c..0000000 --- a/scsi/adapters/scsi_user_dma.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ -/* - * File: scsi_user_dma.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 4/91 - * - * Defines for Mach 2.5 compat, user-space DMA routines - */ - -/* There is one such structure per I/O device - that needs to xfer data to/from user space */ - -typedef struct fdma { - vm_offset_t kernel_virtual; - vm_size_t max_data; - vm_offset_t user_virtual; - int xfer_size_rnd; -} *fdma_t; - -extern int - fdma_init(/* fdma_t, vm_size_t */), - fdma_map(/* fdma_t, struct buf* */), - fdma_unmap(/* fdma_t, struct buf* */); diff --git a/scsi/compat_30.h b/scsi/compat_30.h deleted file mode 100644 index 988aed7..0000000 --- a/scsi/compat_30.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: compat_30.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 4/91 - * - * Compatibility defs to retrofit Mach 3.0 drivers - * into Mach 2.6. - */ - -#ifndef _SCSI_COMPAT_30_ -#define _SCSI_COMPAT_30_ - -#include <kern/assert.h> - -#ifdef MACH_KERNEL -/* - * Mach 3.0 compiles with these definitions - */ - -#include <device/param.h> -#include <device/io_req.h> -#include <device/device_types.h> -#include <device/disk_status.h> - -/* - * Scratch temporary in io_req structure (for error handling) - */ -#define io_temporary io_error - -#else /*MACH_KERNEL*/ -/* - * Mach 2.x compiles with these definitions - */ - -/* ??? */ -typedef int dev_mode_t; -typedef int *dev_status_t; /* Variable-length array of integers */ -/* ??? */ - -/* Buffer structures */ - -typedef int io_return_t; - -#include <sys/param.h> -#include <sys/buf.h> - -#define io_req buf -typedef struct buf *io_req_t; - -#define io_req_alloc(ior,size) ior = geteblk(size) -#define io_req_free(ior) brelse(ior) - -/* - * Redefine fields for drivers using new names - */ -#define io_op b_flags -#define io_count b_bcount -#define io_error b_error -#define io_unit b_dev -#define io_recnum b_blkno -#define io_residual b_resid -#define io_data b_un.b_addr -#define io_done b_iodone - -/* - * Redefine fields for driver request list heads, using new names. - */ -#define io_next av_forw -#define io_prev av_back -/*#define io_next b_actf*/ -/*#define io_prev b_actl*/ -#define io_link b_forw -#define io_rlink b_back -/*#define io_count b_active*/ -/*#define io_residual b_errcnt*/ -#define io_alloc_size b_bufsize - -/* - * Scratch temporary in io_req structure (for error handling) - */ -#define io_temporary b_pfcent - -/* - * Redefine flags - */ -#define IO_WRITE B_WRITE -#define IO_READ B_READ -#define IO_OPEN B_OPEN -#define IO_DONE B_DONE -#define IO_ERROR B_ERROR -#define IO_BUSY B_BUSY -#define IO_WANTED B_WANTED -#define IO_BAD B_BAD -#define IO_CALL B_CALL -#define IO_INTERNAL B_MD1 - -#define IO_SPARE_START B_MD1 - -#include <sys/disklabel.h> - -/* Error codes */ - -#include <sys/errno.h> - -#define D_SUCCESS ESUCCESS -#define D_IO_ERROR EIO -#define D_NO_SUCH_DEVICE ENXIO -#define D_INVALID_SIZE EINVAL -#define D_ALREADY_OPEN EBUSY -#define D_INVALID_OPERATION EINVAL -#define D_NO_MEMORY ENOMEM -#define D_WOULD_BLOCK EWOULDBLOCK -#define D_DEVICE_DOWN EIO -#define D_READ_ONLY EROFS - -/* - * Debugging support - */ -#define db_printf kdbprintf -#define db_printsym(s,m) kdbpsymoff(s,1,"") - -/* - * Miscellaneous utils - */ - -#define check_memory(addr,dow) ((dow) ? wbadaddr(addr,4) : badaddr(addr,4)) - -#include <sys/kernel.h> /* for hz */ -#include <scsi/adapters/scsi_user_dma.h> - -#ifdef DECSTATION -#include <mach/mips/vm_param.h> /* for page size */ -#define ULTRIX_COMPAT 1 /* support for rzdisk disk formatter */ -#endif /*DECSTATION*/ - -#endif /*MACH_KERNEL*/ - -#endif /*_SCSI_COMPAT_30_*/ diff --git a/scsi/disk_label.c b/scsi/disk_label.c deleted file mode 100644 index ab20378..0000000 --- a/scsi/disk_label.c +++ /dev/null @@ -1,692 +0,0 @@ -/* - * Copyright (c) 1996 The University of Utah and - * the Computer Systems Laboratory at the University of Utah (CSL). - * All rights reserved. - * - * Permission to use, copy, modify and distribute this software is hereby - * granted provided that (1) source code retains these copyright, permission, - * and disclaimer notices, and (2) redistributions including binaries - * reproduce the notices in supporting documentation, and (3) all advertising - * materials mentioning features or use of this software display the following - * acknowledgement: ``This product includes software developed by the - * Computer Systems Laboratory at the University of Utah.'' - * - * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS - * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF - * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * CSL requests users of this software to return to csl-dist@cs.utah.edu any - * improvements that they make and grant CSL redistribution rights. - * - * Author: Kevin T. Van Maren, University of Utah CSL - */ - -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ - -/* - * Copyright (c) 1994 Shantanu Goel - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * THE AUTHOR ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. THE AUTHOR DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - */ - -/* This file contains the partition code that is used by the Mach - * device drivers (ide & scsi). */ - -#include <scsi/compat_30.h> -#include <sys/types.h> - -#include <scsi/rz_labels.h> -#include <i386at/disk.h> /* combine & rename these... */ - -#define SECTOR_SIZE 512 /* BAD!!! */ - -#define DSLICE(dev) ((dev >> 4) & 0x3f) -#define DPART(dev) (dev & 0xf) - -/* note: 0 will supress ALL output; - 1 is 'normal' output; 2 is verbose; 3 is Very verbose */ -#define PARTITION_DEBUG 1 - -#define min(x,y) (x<y?x:y) - -/* - * Label that is filled in with extra info - */ -struct disklabel default_label = -{ - DISKMAGIC, DTYPE_SCSI, 0, - "SCSI", "", - DEV_BSIZE, 1, 1, 1, 1, 1, 0, 0, 0, - 3600, 1, 1, 1, 0, 0, 0, - {0,}, {0,}, - DISKMAGIC, 0, - 8, 8192, 8192, - {{ -1, 0, 1024, FS_BSDFFS, 8, 3 }, - { -1, 0, 1024, FS_BSDFFS, 8, 3 }, - { -1, 0, 1024, FS_BSDFFS, 8, 3 }, - { -1, 0, 1024, FS_BSDFFS, 8, 3 }, - { -1, 0, 1024, FS_BSDFFS, 8, 3 }, - { -1, 0, 1024, FS_BSDFFS, 8, 3 }, - { -1, 0, 1024, FS_BSDFFS, 8, 3 }, - { -1, 0, 1024, FS_BSDFFS, 8, 3 }} -}; - - - -/* the device driver calls this just to save some info it got from the HW */ -/* This is a bad holdover from the disklabel days, and needs to go */ -fudge_bsd_label(struct disklabel *label, int type, int total_secs, int heads, int sectors, int sectorsize, int n) -{ - *label=default_label; - - label->d_ncylinders = total_secs/(heads*sectors); - label->d_ntracks = heads; - label->d_nsectors = sectors; - - label->d_secpercyl = heads*sectors; - label->d_secperunit = total_secs; - - /* this is never used, but ... */ - label->d_partitions[MAXPARTITIONS].p_offset = 0; - label->d_partitions[MAXPARTITIONS].p_size = total_secs; - - /* ?? - */ - label->d_secsize = sectorsize; - label->d_type = type; - label->d_subtype = 0xa; /* ??? */ - - label->d_npartitions = n; /* up to 'c' */ - label->d_checksum = 0; - - /* should do a checksum on it now */ -} - - - -/* This is placed here to - a. provide comparability with existing servers - b. allow the use of FreeBSD-style slices to access ANY disk partition - c. provide an easy migration path to lites-based partition code - by only passing the drive name to get the entire disk (sd0). - - This will be called by every routine that needs to access partition info - based on a device number. It is slower than the old method of indexing - into a disklabel, but is more flexible, and reasonably fast in the (future) - case where Lites will access the whole disk. An array of disklabels - could have been used, but this is more compact and general. The underlying - structure does not limit it to 2-levels, but keeping the kernel interface - simple does. */ - - -/* this code and data structure based on conversation with Bryan Ford */ -/* Note: this is called ON EVERY read or write. It makes sense to - optimize this for the common case. Hopefully the common case - will become the '0,0' case, as partitioning is moved out of the - kernel. (Downside is kernel can't protect filesystems from each other). - It is slower than indexing into a 1-D array, but not much. */ - -struct diskpart *lookup_part(struct diskpart *array, int dev_number) -{ -/* Note: 10 bit encoding to get partitions 0-15 (0,a-h typically), and slices - * 0-63 - */ - - int slice = DSLICE(dev_number); - int part = DPART(dev_number); - struct diskpart *s; - - if (slice == 0) /* compatability slice */ - { - if (part == 0) /* whole disk */ - return &array[0]; - - if (array[0].type == DISKPART_DOS) - { - int i; - for (i = 0; i < array[0].nsubs; i++) - { - s = &array[0].subs[i]; - if ( s->type == DISKPART_BSD - || s->type == DISKPART_VTOC) - { - if (part > s->nsubs) - return 0; - return (&s->subs[part-1]); - } - } - } - - if (part > array[0].nsubs) - return 0; - return(&array[0].subs[part-1]); - } - else - { - if ( array[0].type != DISKPART_DOS - || slice > array[0].nsubs) - return 0; - - s = &array[0].subs[slice-1]; - - if (part == 0) /* whole slice */ - return (s); - if (part > s->nsubs) - return 0; - - return (&s->subs[part-1]); - } -} - - - - -static inline void fill_array(struct diskpart *array, int start, int size, - struct diskpart *subs, int nsubs, short type, short fsys) -{ - array->start=start; - array->size=size; - array->subs=subs; - array->nsubs=nsubs; - array->type=type; - array->fsys=fsys; -#if (PARTITION_DEBUG > 2) - printf("fill: type %d:%d, start %d, size %d, %d parts\n",type,fsys, - start,size,nsubs); -#endif -} - - - - -void print_array(struct diskpart *array, int level) -{ - int i,j; - struct diskpart *subs; - -#if (PARTITION_DEBUG) - subs=array[0].subs; - - for (i=0;i<array[0].nsubs;i++) { - for (j=0;j<level;j++) - printf(" "); - printf("%c: %d, %d, %d, %d (%d subparts)\n",'a'+i, - subs[i].start, subs[i].size, subs[i].fsys, - subs[i].type, subs[i].nsubs); - if (subs[i].nsubs>0) - print_array(&subs[i], level+1); - } -#endif -} - - - -/* individual routines to find the drive labels. - There needs to be a function for every different method for partitioning - much of the following code is derived from the SCSI/IDE drivers */ - -int get_dos(struct diskpart *array, char *buff, int start, - void *driver_info, int (*bottom_read_fun)(), - char *name, int max_part) -{ - - bios_label_t *mp; - struct bios_partition_info *pp; - - int count, i, j; - int pstart, psize; - int ext=-1, mystart=start, mybase; - int first=1; - - /* note: start is added, although a start != 0 is meaningless - to DOS and anything else... */ - - /* check the boot sector for a partition table. */ - (*bottom_read_fun)(driver_info, start, buff); /* always in sector 0 */ - - /* - * Check for valid partition table. - */ - mp = (bios_label_t *)&buff[BIOS_LABEL_BYTE_OFFSET]; - if (mp->magic != BIOS_LABEL_MAGIC) { -#if (PARTITION_DEBUG>1) - printf("%s invalid partition table\n", name); -#endif - return(0); /* didn't add any partitions */ - } -#if (PARTITION_DEBUG>1) - printf("DOS partition table found\n"); -#endif - - count=min(4,max_part); /* always 4 (primary) partitions */ -#if (PARTITION_DEBUG) - if (count<4) printf("More partitions than space!\n"); -#endif - - - /* fill the next 4 entries in the array */ - for (i=0, pp=(struct bios_partition_info *)mp->partitions; - i<count; i++,pp++) { - - fill_array(&array[i], pp->offset, pp->n_sectors, NULL, 0, - DISKPART_NONE, pp->systid); - if ((pp->systid == DOS_EXTENDED) &&(ext<0)) { - mystart+=pp->offset; - ext=i; - } - } - - /* if there is an extended partition, find all the logical partitions */ - /* note: logical start at '5' (extended is one of the numbered 1-4) */ - - /* logical partitions 'should' be nested inside the primary, but - then it would be impossible to NAME a disklabel inside a logical - partition, which would be nice to do */ -#if (PARTITION_DEBUG>1) - if (ext>=0) - printf("extended partition found: %d\n",ext); -#endif 0 - - while (ext>=0) { - pp = &(((struct bios_partition_info *)mp->partitions)[ext]); - - /* read the EXTENDED partition table */ - if (first) { - mybase=mystart; - first=0; - } else { - mybase=mystart+pp->offset; - } - - (*bottom_read_fun)(driver_info, mybase, buff); - - if (mp->magic != BIOS_LABEL_MAGIC) { -#if (PARTITION_DEBUG>1) - printf("%s invalid expanded magic\n", name); -#endif - return(count);/*don't add any more partitions*/ - } - - /* just in case more than one partition is there...*/ - /* search the EXTENDED partition table */ - ext=-1; - for (j=0,pp=(struct bios_partition_info *)mp->partitions; - j<4; j++,pp++) { - - if (pp->systid && (pp->systid!=DOS_EXTENDED)) { - if (count<max_part) { - fill_array(&array[count], - mybase +pp->offset, - pp->n_sectors, NULL, 0, DISKPART_NONE, - pp->systid); - count++; } - else { -#if (PARTITION_DEBUG) - printf("More partitions than space!\n"); -#endif - return(count); - } - } else if ((ext<0) &&(pp->systid==DOS_EXTENDED)) { - ext=j; - /* recursivly search the chain here */ - } - } - } -#if (PARTITION_DEBUG>1) - printf("%d dos partitions\n",count); -#endif 0 - return(count); /* number dos partitions found */ - -} - - - -/* this should work on the bare drive, or in a dos partition */ -int get_disklabel(struct diskpart *array, char *buff, int start, - void *driver_info, int (*bottom_read_fun)(), - char *name, int max_part) -{ - struct disklabel *dlp; - int mybase = start + (512 * LBLLOC)/SECTOR_SIZE, i; - int count; - - (*bottom_read_fun)(driver_info, mybase, buff); - - dlp = (struct disklabel *)buff; - if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { -#if (PARTITION_DEBUG>1) - printf("%s no BSD label found\n",name); -#endif - return(0); /* no partitions added */ - } -#if (PARTITION_DEBUG>1) - printf(" BSD LABEL\n"); -#endif 0 - /* note: BSD disklabel offsets are from start of DRIVE -- uuggh */ - - count=min(8,max_part); /* always 8 in a disklabel */ -#if (PARTITION_DEBUG) - if (count<8) printf("More partitions than space!\n"); -#endif - /* COPY into the array */ - for (i=0;i<count;i++) - fill_array(&array[i], /* mybase + */ - dlp->d_partitions[i].p_offset, - dlp->d_partitions[i].p_size, - NULL, 0, DISKPART_NONE, dlp->d_partitions[i].p_fstype); - - /* note: p_fstype is not the same set as the DOS types */ - - return(count); /* 'always' 8 partitions in disklabel -- if space */ - -/* UNREACHED CODE FOLLOWS: (alternative method in scsi) */ -#if 0 - (*bottom_read_fun)(driver_info, (start)+LABELSECTOR, buff); - - register int j; - boolean_t found; - - for (j = LABELOFFSET, found = FALSE; - j < (SECTOR_SIZE-sizeof(struct disklabel)); - j += sizeof(int)) { - search = (struct disklabel *)&buff[j]; - if (search->d_magic == DISKMAGIC && - search->d_magic2 == DISKMAGIC) { - found = TRUE; - break; - } - } - if (found) { -#if (PARTITION_DEBUG>1) - printf("Label found in LABELSECTOR\n"); -#endif - } else { - search = 0; - } - - -#endif 0 - -} - - -/* NOT TESTED! */ -/* VTOC in sector 29 */ -int get_vtoc(struct diskpart *array, char *buff, int start, - void *driver_info, int (*bottom_read_fun)(), - char *name, int max_part) -{ - struct evtoc *evp; - int n,i; - struct disklabel lpl; - struct disklabel *lp = &lpl; - -#if (PARTITION_DEBUG) - printf("Read VTOC.\n"); -#endif - (*bottom_read_fun)(driver_info, start +PDLOCATION, buff); - evp = (struct evtoc *)buff; - if (evp->sanity != VTOC_SANE) { -#if (PARTITION_DEBUG) - printf("%s evtoc corrupt or not found\n", name); -#endif - return(0); - } - n = min(evp->nparts,max_part); /* no longer DISKLABEL limitations... */ -#if 0 - n = (evp->nparts > MAXPARTITIONS) ? MAXPARTITIONS : evp->nparts; -#endif 0 - - for (i = 0; i < n; i++) - fill_array(&array[i], /* mybase + */ - evp->part[i].p_start, - evp->part[i].p_size, - NULL, 0, DISKPART_NONE, FS_BSDFFS); - - return(n); /* (evp->nparts) */ -} - - -/* NOT TESTED! */ -int get_omron(struct diskpart *array, char *buff, int start, - void *driver_info, int (*bottom_read_fun)(), - char *name, int max_part) -{ - - struct disklabel *label; - - /* here look for an Omron label */ - register omron_label_t *part; - int i; - -#if (PARTITION_DEBUG) - printf("Looking for Omron label...\n"); -#endif - - (*bottom_read_fun)(driver_info, start+ - OMRON_LABEL_BYTE_OFFSET/SECTOR_SIZE, buff); - - part = (omron_label_t*)&buff[OMRON_LABEL_BYTE_OFFSET%SECTOR_SIZE]; - if (part->magic == OMRON_LABEL_MAGIC) { -#if (PARTITION_DEBUG) - printf("{Using OMRON label}"); -#endif - for (i = 0; i < 8; i++) { - label->d_partitions[i].p_size = part->partitions[i].n_sectors; - label->d_partitions[i].p_offset = part->partitions[i].offset; - } - bcopy(part->packname, label->d_packname, 16); - label->d_ncylinders = part->ncyl; - label->d_acylinders = part->acyl; - label->d_ntracks = part->nhead; - label->d_nsectors = part->nsect; - /* Many disks have this wrong, therefore.. */ -#if 0 - label->d_secperunit = part->maxblk; -#else - label->d_secperunit = label->d_ncylinders * label->d_ntracks * - label->d_nsectors; -#endif 0 - - return(8); - } -#if (PARTITION_DEBUG) - printf("No Omron label found.\n"); -#endif - return(0); -} - - -/* NOT TESTED! */ -int get_dec(struct diskpart *array, char *buff, int start, - void *driver_info, int (*bottom_read_fun)(), - char *name, int max_part) -{ - struct disklabel *label; - - /* here look for a DEC label */ - register dec_label_t *part; - int i; - -#if (PARTITION_DEBUG) - printf("Checking for dec_label...\n"); -#endif - - (*bottom_read_fun)(driver_info, start + - DEC_LABEL_BYTE_OFFSET/SECTOR_SIZE, buff); - - if (part->magic == DEC_LABEL_MAGIC) { -#if (PARTITION_DEBUG) - printf("{Using DEC label}"); -#endif - for (i = 0; i < 8; i++) { - label->d_partitions[i].p_size = part->partitions[i].n_sectors; - label->d_partitions[i].p_offset = part->partitions[i].offset; - } - return(8); - } -#if (PARTITION_DEBUG) - printf("No dec label found.\n"); -#endif - - return(0); -} - - - - -/* array is a pointer to an array of partition_info structures */ -/* array_size is the number of pre-allocated entries there are */ -int get_only_partition(void *driver_info, int (*bottom_read_fun)(), - struct diskpart *array, int array_size, - int disk_size, char *drive_name) -{ - char buff[SECTOR_SIZE]; - int i,n,cnt; - int arrsize; - struct diskpart *res; - - /* first fill in the entire disk stuff */ - /* or should the calling routine do that already? */ - - fill_array(array, 0, disk_size, NULL, 0, -1, -1); - - /* while the structure does not preclude additional nestings, - additional ones make no sense currently, so they are not - checked (Mach can't handle them anyway). It might be nice - if for all partitions found, all types of sub-partitions - were looked for (unnecessary). This will be done when this - is moved out of ther kernel, and there is some way to name them */ - - arrsize = array_size -1; /* 1 for whole disk */ - - /* search for dos partition table */ - /* find all the partitions (including logical) */ - n=get_dos(&array[1], buff, 0, - driver_info, (bottom_read_fun), drive_name, - arrsize); - - if (n>0) { - fill_array(array, 0, disk_size, &array[1], n, - DISKPART_DOS, 256+DISKPART_DOS); - arrsize-=n; - - - /* search each one for a BSD disklabel (iff BSDOS) */ - /* note: searchine extended and logical partitions */ - for (i=0;i<n;i++) - if (array[i+1].fsys==BSDOS) { -#if (PARTITION_DEBUG) - printf("BSD OS slice: %d\n",i+1); -#endif - cnt=get_disklabel(&array[n+1], buff, - array[i+1].start, - driver_info, (bottom_read_fun), - drive_name,arrsize); - - if (cnt>0) { - arrsize-=cnt; - fill_array(&array[i+1],array[i+1].start, - array[i+1].size, &array[n+1], - cnt, DISKPART_BSD, - array[i+1].fsys); - } - n+=cnt; - } - - /* search for VTOC -- in a DOS partition as well */ - for (i=0;i<n;i++) - if (array[i+1].fsys==UNIXOS) { -#if (PARTITION_DEBUG) - printf("UNIXOS (vtoc) partition\n"); -#endif - cnt=get_vtoc(&array[n+1], buff, - array[i+1].start, - driver_info, (bottom_read_fun), - drive_name,arrsize); - - if (cnt>0) { - arrsize-=cnt; - fill_array(&array[i+1],array[i+1].start, - array[i+1].size, &array[n+1], - cnt, DISKPART_VTOC, - array[i+1].fsys); - } - n+=cnt; - } - } - - /* search for only disklabel */ - if (n==0) { - fill_array(array, 0, disk_size, &array[1], n, DISKPART_BSD, - 256+DISKPART_BSD); - n=get_disklabel(&array[1], buff, 0, driver_info, - (bottom_read_fun), drive_name,arrsize); - } - - /* search for only VTOC -- NOT TESTED! */ - if (n==0) { - fill_array(array, 0, disk_size, &array[1], n, DISKPART_VTOC, - 256+DISKPART_VTOC); - n=get_vtoc(&array[1], buff, 0, driver_info, (bottom_read_fun), - drive_name,arrsize); - } -#if 0 - /* search for only omron -- NOT TESTED! */ - if (n==0) { - fill_array(array, 0, disk_size, &array[1], n, DISKPART_OMRON, - 256+DISKPART_OMRON); - n=get_omron(&array[1], buff, 0,driver_info, (bottom_read_fun), - drive_name,arrsize); - } - - /* search for only dec -- NOT TESTED! */ - if (n==0) { - fill_array(array, 0, disk_size, &array[1], n, DISKPART_DEC, - 256+DISKPART_DEC); - n=get_dec(&array[1], buff, 0, driver_info, (bottom_read_fun), - drive_name,arrsize); - } -#endif 0 - -#if (PARTITION_DEBUG) /* print out what we found */ - print_array(array,0); -#endif - -} - - diff --git a/scsi/mapped_scsi.c b/scsi/mapped_scsi.c deleted file mode 100644 index fe3dd77..0000000 --- a/scsi/mapped_scsi.c +++ /dev/null @@ -1,586 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: mapped_scsi.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 9/90 - * - * In-kernel side of the user-mapped SCSI driver. - */ - -#include <asc.h> -#include <sii.h> -#define NRZ (NASC+NSII) -#if NRZ > 0 -#include <platforms.h> - -#include <machine/machspl.h> /* spl definitions */ - -#include <device/device_types.h> -#include <device/io_req.h> -#include <chips/busses.h> - -#include <vm/vm_kern.h> -#include <kern/eventcount.h> - -#include <scsi/mapped_scsi.h> - -#include <machine/machspl.h> - -#ifdef DECSTATION - -#define machine_btop mips_btop - -#define kvctophys(v) K0SEG_TO_PHYS((v)) /* kernel virtual cached */ -#define phystokvc(p) PHYS_TO_K0SEG((p)) /* and back */ -#define kvutophys(v) K1SEG_TO_PHYS((v)) /* kernel virtual uncached */ -#define phystokvu(p) PHYS_TO_K1SEG((p)) /* and back */ - -#include <mips/mips_cpu.h> -#include <mips/PMAX/kn01.h> -#include <mips/PMAX/pmaz_aa.h> - -#define SII_REG_PHYS(self) kvutophys(self->registers.any) -#define SII_RAM_PHYS(self) (SII_REG_PHYS((self))+(KN01_SYS_SII_B_START-KN01_SYS_SII)) -#define SII_RAM_SIZE (KN01_SYS_SII_B_END-KN01_SYS_SII_B_START) - -#define ASC_REG_PHYS(self) kvutophys(self->registers.any) -#define ASC_DMAR_PHYS(self) (ASC_REG_PHYS((self))+ ASC_OFFSET_DMAR) -#define ASC_RAM_PHYS(self) (ASC_REG_PHYS((self))+ ASC_OFFSET_RAM) - -#define PAD_7061(n) short n -#define PAD_53C94(n) char n[3] - -#endif /*DECSTATION*/ - -#ifdef VAXSTATION -#define machine_btop vax_btop -#endif /*VAXSTATION*/ - -#ifdef P40 - -#define machine_btop mips_btop - -#define kvctophys(v) K0SEG_TO_PHYS((v)) /* kernel virtual cached */ -#define phystokvc(p) PHYS_TO_K0SEG((p)) /* and back */ -#define kvutophys(v) K1SEG_TO_PHYS((v)) /* kernel virtual uncached */ -#define phystokvu(p) PHYS_TO_K1SEG((p)) /* and back */ - -#include <mips/mips_cpu.h> - -#define ASC_RAM_SIZE 0 -#define ASC_OFFSET_DMAR 0 -#define ASC_OFFSET_RAM 0 - -#define ASC_REG_PHYS(self) kvutophys(self->registers.any) -#define ASC_DMAR_PHYS(self) (ASC_REG_PHYS((self))+ ASC_OFFSET_DMAR) -#define ASC_RAM_PHYS(self) (ASC_REG_PHYS((self))+ ASC_OFFSET_RAM) -#endif /* P40 */ - -/* - * Phys defines for the various supported HBAs - */ - -/* DEC7061 */ -#include <scsi/adapters/scsi_7061.h> - -#ifdef PAD_7061 - -typedef struct { - volatile unsigned short sii_sdb; /* rw: Data bus and parity */ - PAD_7061(pad0); - volatile unsigned short sii_sc1; /* rw: scsi signals 1 */ - PAD_7061(pad1); - volatile unsigned short sii_sc2; /* rw: scsi signals 2 */ - PAD_7061(pad2); - volatile unsigned short sii_csr; /* rw: control and status */ - PAD_7061(pad3); - volatile unsigned short sii_id; /* rw: scsi bus ID */ - PAD_7061(pad4); - volatile unsigned short sii_sel_csr; /* rw: selection status */ - PAD_7061(pad5); - volatile unsigned short sii_destat; /* ro: selection detector status */ - PAD_7061(pad6); - volatile unsigned short sii_dstmo; /* unsupp: dssi timeout */ - PAD_7061(pad7); - volatile unsigned short sii_data; /* rw: data register */ - PAD_7061(pad8); - volatile unsigned short sii_dma_ctrl; /* rw: dma control reg */ - PAD_7061(pad9); - volatile unsigned short sii_dma_len; /* rw: length of transfer */ - PAD_7061(pad10); - volatile unsigned short sii_dma_adr_low;/* rw: low address */ - PAD_7061(pad11); - volatile unsigned short sii_dma_adr_hi; /* rw: high address */ - PAD_7061(pad12); - volatile unsigned short sii_dma_1st_byte;/* rw: initial byte */ - PAD_7061(pad13); - volatile unsigned short sii_stlp; /* unsupp: dssi short trgt list ptr */ - PAD_7061(pad14); - volatile unsigned short sii_ltlp; /* unsupp: dssi long " " " */ - PAD_7061(pad15); - volatile unsigned short sii_ilp; /* unsupp: dssi initiator list ptr */ - PAD_7061(pad16); - volatile unsigned short sii_dssi_csr; /* unsupp: dssi control */ - PAD_7061(pad17); - volatile unsigned short sii_conn_csr; /* rc: connection interrupt control */ - PAD_7061(pad18); - volatile unsigned short sii_data_csr; /* rc: data interrupt control */ - PAD_7061(pad19); - volatile unsigned short sii_cmd; /* rw: command register */ - PAD_7061(pad20); - volatile unsigned short sii_diag_csr; /* rw: disgnostic status */ - PAD_7061(pad21); -} sii_padded_regmap_t; - -#else /*!PAD_7061*/ - -typedef sii_regmap_t sii_padded_regmap_t; - -#endif /*!PAD_7061*/ - -/* NCR 53C94 */ -#include <scsi/adapters/scsi_53C94.h> - -#ifdef PAD_53C94 -typedef struct { - volatile unsigned char asc_tc_lsb; /* rw: Transfer Counter LSB */ - PAD_53C94(pad0); - volatile unsigned char asc_tc_msb; /* rw: Transfer Counter MSB */ - PAD_53C94(pad1); - volatile unsigned char asc_fifo; /* rw: FIFO top */ - PAD_53C94(pad2); - volatile unsigned char asc_cmd; /* rw: Command */ - PAD_53C94(pad3); - volatile unsigned char asc_csr; /* r: Status */ -/*#define asc_dbus_id asc_csr /* w: Destination Bus ID */ - PAD_53C94(pad4); - volatile unsigned char asc_intr; /* r: Interrupt */ -/*#define asc_sel_timo asc_intr /* w: (re)select timeout */ - PAD_53C94(pad5); - volatile unsigned char asc_ss; /* r: Sequence Step */ -/*#define asc_syn_p asc_ss /* w: synchronous period */ - PAD_53C94(pad6); - volatile unsigned char asc_flags; /* r: FIFO flags + seq step */ -/*#define asc_syn_o asc_flags /* w: synchronous offset */ - PAD_53C94(pad7); - volatile unsigned char asc_cnfg1; /* rw: Configuration 1 */ - PAD_53C94(pad8); - volatile unsigned char asc_ccf; /* w: Clock Conv. Factor */ - PAD_53C94(pad9); - volatile unsigned char asc_test; /* w: Test Mode */ - PAD_53C94(pad10); - volatile unsigned char asc_cnfg2; /* rw: Configuration 2 */ - PAD_53C94(pad11); - volatile unsigned char asc_cnfg3; /* rw: Configuration 3 */ - PAD_53C94(pad12); - volatile unsigned char asc_rfb; /* w: Reserve FIFO byte */ - PAD_53C94(pad13); -} asc_padded_regmap_t; - -#else /* !PAD_53C94 */ - -typedef asc_regmap_t asc_padded_regmap_t; - -#endif /* !PAD_53C94 */ - -/* - * Co-existency with in-kernel drivers - */ -boolean_t rz_use_mapped_interface = FALSE; - -/* - * Status information for all HBAs - */ -/*static*/ struct RZ_status { - union { - unsigned long any; - asc_padded_regmap_t *asc; - sii_padded_regmap_t *sii; - } registers; - int (*stop)(); - vm_offset_t (*mmap)(); - mapped_scsi_info_t info; - struct evc eventcounter; -} RZ_statii[NRZ]; - -typedef struct RZ_status *RZ_status_t; - - -/* - * Probe routine for all HBAs - */ -RZ_probe(regbase, ui, hba) - unsigned long regbase; - register struct bus_device *ui; -{ - int unit = ui->unit; - vm_offset_t addr; - mapped_scsi_info_t info; - struct RZ_status *self; - - printf("[mappable] "); - - self = &RZ_statii[unit]; - - self->registers.any = regbase; - - /* - * Grab a page to be mapped later to users - */ - (void) kmem_alloc_wired(kernel_map, &addr, PAGE_SIZE); /* kseg2 */ - bzero(addr, PAGE_SIZE); - addr = pmap_extract(pmap_kernel(), addr); /* phys */ - info = (mapped_scsi_info_t) (phystokvc(addr)); - self->info = info; - - /* - * Set permanent info - */ - info->interrupt_count = 0; -/*XXX*/ info->ram_size = ASC_RAM_SIZE; - info->hba_type = hba; - - evc_init(&self->eventcounter); - info->wait_event = self->eventcounter.ev_id; - - return 1; -} - -/* - * Device open procedure - */ -RZ_open(dev, flag, ior) - io_req_t ior; -{ - int unit = dev; - register RZ_status_t self = &RZ_statii[unit]; - - - if (unit >= NRZ) - return D_NO_SUCH_DEVICE; - - /* - * Silence interface, just in case - */ - (*self->stop)(unit); - - /* - * Reset eventcounter - */ - evc_signal(&self->eventcounter); - - rz_use_mapped_interface = TRUE; - - /* - * Do not turn interrupts on. The user can do it when ready - * to take them. - */ - - return 0; -} - -/* - * Device close procedure - */ -RZ_close(dev, flag) -{ - int unit = dev; - register RZ_status_t self = &RZ_statii[unit]; - - if (unit >= NRZ) - return D_NO_SUCH_DEVICE; - - /* - * Silence interface, in case user forgot - */ - (*self->stop)(unit); - - evc_signal(&self->eventcounter); - - rz_use_mapped_interface = FALSE; - - /* XXX rz_kernel_mode(); XXX */ - - return 0; -} - - -/* - * Get status procedure. - * We need to tell that we are mappable. - */ -io_return_t -RZ_get_status(dev, flavor, status, status_count) - int dev; - int flavor; - dev_status_t status; - unsigned int status_count; -{ - return (D_SUCCESS); -} - -/* - * Should not refuse this either - */ -RZ_set_status(dev, flavor, status, status_count) - int dev; - int flavor; - dev_status_t status; - unsigned int status_count; -{ - return (D_SUCCESS); -} - -/* - * Port death notification routine - */ -RZ_portdeath(dev, dead_port) -{ -} - -/* - * Page mapping, switch off to HBA-specific for regs&ram - */ -vm_offset_t -RZ_mmap(dev, off, prot) - int dev; -{ - int unit = dev; - register RZ_status_t self = &RZ_statii[unit]; - vm_offset_t page; - vm_offset_t addr; - io_return_t ret; - - if (off < SCSI_INFO_SIZE) { - addr = kvctophys (self->info) + off; - ret = D_SUCCESS; - } else - ret = (*self->mmap)(self, off, prot, &addr); - - if (ret != D_SUCCESS) - return ret; - - page = machine_btop(addr); - - return (page); -} - - -/* - *--------------------------------------------------------------- - * The rest of the file contains HBA-specific routines - *--------------------------------------------------------------- - */ - -#if NASC > 0 -/* - * Routines for the NCR 53C94 - */ -static -ASC_stop(unit) -{ - register RZ_status_t self = &RZ_statii[unit]; - register asc_padded_regmap_t *regs = self->registers.asc; - int ack; - - ack = regs->asc_intr; /* Just acknowledge pending interrupts */ -} - -ASC_probe(reg, ui) - unsigned long reg; - register struct bus_device *ui; -{ - register RZ_status_t self = &RZ_statii[ui->unit]; - static vm_offset_t ASC_mmap(); - - self->stop = ASC_stop; - self->mmap = ASC_mmap; - return RZ_probe(reg, ui, HBA_NCR_53c94); -} - - -ASC_intr(unit,spllevel) - spl_t spllevel; -{ - register RZ_status_t self = &RZ_statii[unit]; - register asc_padded_regmap_t *regs = self->registers.asc; - register csr, intr, seq_step, cmd; - - /* - * Acknowledge interrupt request - * - * This clobbers some two other registers, therefore - * we read them beforehand. It also clears the intr - * request bit, silencing the interface for now. - */ - csr = regs->asc_csr; - - /* drop spurious interrupts */ - if ((csr & ASC_CSR_INT) == 0) - return; - seq_step = regs->asc_ss; - cmd = regs->asc_cmd; - - intr = regs->asc_intr; /* ack */ - - splx(spllevel); /* drop priority */ - - if (self->info) { - self->info->interrupt_count++; /* total interrupts */ - self->info->saved_regs.asc.csr = csr; - self->info->saved_regs.asc.isr = intr; - self->info->saved_regs.asc.seq = seq_step; - self->info->saved_regs.asc.cmd = cmd; - } - - /* Awake user thread */ - evc_signal(&self->eventcounter); -} - -/* - * Virtual->physical mapping routine for PMAZ-AA - */ -static vm_offset_t -ASC_mmap(self, off, prot, addr) - RZ_status_t self; - vm_offset_t off; - vm_prot_t prot; - vm_offset_t *addr; -{ - /* - * The offset (into the VM object) defines the following layout - * - * off size what - * 0 1pg mapping information (csr & #interrupts) - * 1pg 1pg ASC registers - * 2pg 1pg ASC dma - * 3pg 128k ASC ram buffers - */ - -#define ASC_END (ASC_RAM_BASE+ASC_RAM_SIZE) - - if (off < ASC_DMAR_BASE) - *addr = (vm_offset_t) ASC_REG_PHYS(self) + (off - SCSI_INFO_SIZE); - else if (off < ASC_RAM_BASE) - *addr = (vm_offset_t) ASC_DMAR_PHYS(self) + (off - ASC_REGS_BASE); - else if (off < ASC_END) - *addr = (vm_offset_t) ASC_RAM_PHYS(self) + (off - ASC_RAM_BASE); - else - return D_INVALID_SIZE; - - return D_SUCCESS; -} -#endif NASC > 0 - -#if NSII > 0 -SII_stop(unit) -{ - register RZ_status_t self = &RZ_statii[unit]; - register sii_padded_regmap_t *regs = self->registers.sii; - - regs->sii_csr &= ~SII_CSR_IE; /* disable interrupts */ - /* clear all wtc bits */ - regs->sii_conn_csr = regs->sii_conn_csr; - regs->sii_data_csr = regs->sii_data_csr; -} - -SII_probe(reg, ui) - unsigned long reg; - register struct bus_device *ui; -{ - register RZ_status_t self = &RZ_statii[ui->unit]; - static vm_offset_t SII_mmap(); - - self->stop = SII_stop; - self->mmap = SII_mmap; - return RZ_probe(reg, ui, HBA_DEC_7061); -} - -SII_intr(unit,spllevel) - spl_t spllevel; -{ - register RZ_status_t self = &RZ_statii[unit]; - register sii_padded_regmap_t *regs = self->registers.sii; - register unsigned short conn, data; - - /* - * Disable interrupts, saving cause(s) first. - */ - conn = regs->sii_conn_csr; - data = regs->sii_data_csr; - - /* drop spurious calls */ - if (((conn|data) & (SII_DTR_DI|SII_DTR_CI)) == 0) - return; - - regs->sii_csr &= ~SII_CSR_IE; - - regs->sii_conn_csr = conn; - regs->sii_data_csr = data; - - splx(spllevel); - - if (self->info) { - self->info->interrupt_count++; /* total interrupts */ - self->info->saved_regs.sii.sii_conn_csr = conn; - self->info->saved_regs.sii.sii_data_csr = data; - } - - /* Awake user thread */ - evc_signal(&self->eventcounter); -} - -static vm_offset_t -SII_mmap(self, off, prot, addr) - RZ_status_t self; - vm_offset_t off; - vm_prot_t prot; - vm_offset_t *addr; -{ - /* - * The offset (into the VM object) defines the following layout - * - * off size what - * 0 1pg mapping information (csr & #interrupts) - * 1pg 1pg SII registers - * 2pg 128k SII ram buffer - */ - -#define SII_END (SII_RAM_BASE+SII_RAM_SIZE) - - if (off < SII_RAM_BASE) - *addr = (vm_offset_t) SII_REG_PHYS(self) + (off - SCSI_INFO_SIZE); - else if (off < SII_END) - *addr = (vm_offset_t) SII_RAM_PHYS(self) + (off - SII_RAM_BASE); - else - return D_INVALID_SIZE; - - return D_SUCCESS; -} -#endif NSII > 0 - -#endif NRZ > 0 diff --git a/scsi/mapped_scsi.h b/scsi/mapped_scsi.h deleted file mode 100644 index b9c6528..0000000 --- a/scsi/mapped_scsi.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: mapped_scsi.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 11/90 - * - * Definitions for the User-level SCSI Driver - */ - -/* - * HBA chips of various sorts - */ - -/* DEC 7061 used on pmaxen */ - -typedef struct sii_volatile_regs { - unsigned short sii_conn_csr; - unsigned short sii_data_csr; -} *sii_reg_t; - -#define HBA_DEC_7061 0x00000001 - - /* layout of mapped stuff */ -#define SII_REGS_BASE (SCSI_INFO_BASE+SCSI_INFO_SIZE) -#define SII_REGS_SIZE PAGE_SIZE -#define SII_RAM_BASE (SII_REGS_BASE+SII_REGS_SIZE) - - -/* National 53C94, used on 3maxen' PMAZ-AA boards */ - -typedef struct asc_volatile_regs { - unsigned char csr; - unsigned char isr; - unsigned char seq; - unsigned char cmd; -} *asc_reg_t; - -#define HBA_NCR_53c94 0x00000002 - - /* layout of mapped stuff */ -#define ASC_REGS_BASE (SCSI_INFO_BASE+SCSI_INFO_SIZE) -#define ASC_REGS_SIZE PAGE_SIZE -#define ASC_DMAR_BASE (ASC_REGS_BASE+ASC_REGS_SIZE) -#define ASC_DMAR_SIZE PAGE_SIZE -#define ASC_RAM_BASE (ASC_DMAR_BASE+ASC_DMAR_SIZE) - -/* - * User-mapped information block, common to all - */ -#define SCSI_INFO_BASE 0 -#define SCSI_INFO_SIZE PAGE_SIZE - -#define SCSI_MAX_MAPPED_SIZE (ASC_RAM_BASE+128*1024) - -typedef struct { - int interrupt_count;/* Counter kept by kernel */ - unsigned int wait_event; /* To wait for interrupts */ - unsigned ram_size; - int hba_type; /* Tag for regs union */ - union { /* Space for regs saved on - * intr. Only few used */ - struct asc_volatile_regs asc; - struct sii_volatile_regs sii; - } saved_regs; -} *mapped_scsi_info_t; - diff --git a/scsi/pc_scsi_label.c b/scsi/pc_scsi_label.c deleted file mode 100644 index 9bbcbbf..0000000 --- a/scsi/pc_scsi_label.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1993,1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* This goes away as soon as we move it in the Ux server */ - - - -#include <mach/std_types.h> -#include <scsi/compat_30.h> -#include <scsi/scsi.h> -#include <scsi/scsi_defs.h> -#include <scsi/rz.h> -#include <scsi/rz_labels.h> -#include <sys/types.h> -#include <sys/ioctl.h> - -#if (NSCSI > 0) -#define LABEL_DEBUG(x,y) if (label_flag&x) y - -#include <i386at/disk.h> -#include <device/device_types.h> -#include <device/disk_status.h> - - -int scsi_abs_sec = -1; -int scsi_abs_count = -1; - -scsi_rw_abs(dev, data, rw, sec, count) - dev_t dev; -{ - io_req_t ior; - io_return_t error; - - io_req_alloc(ior,0); - ior->io_next = 0; - ior->io_unit = dev & (~(MAXPARTITIONS-1)); /* sort of */ - ior->io_unit |= PARTITION_ABSOLUTE; - ior->io_data = (io_buf_ptr_t)data; - ior->io_count = count; - ior->io_recnum = sec; - ior->io_error = 0; - if (rw == IO_READ) - ior->io_op = IO_READ; - else - ior->io_op = IO_WRITE; - scdisk_strategy(ior); - iowait(ior); - error = ior->io_error; - io_req_free(ior); - return(error); -} - -io_return_t -scsi_i386_get_status(dev, tgt, flavor, status, status_count) -int dev; -target_info_t *tgt; -int flavor; -dev_status_t status; -unsigned int *status_count; -{ - - switch (flavor) { - case V_GETPARMS: { - struct disklabel *lp = &tgt->dev_info.disk.l; - struct disk_parms *dp = (struct disk_parms *)status; - extern struct disklabel default_label; - int part = rzpartition(dev); - - if (*status_count < sizeof (struct disk_parms)/sizeof(int)) - return (D_INVALID_OPERATION); - dp->dp_type = DPT_WINI; - dp->dp_secsiz = lp->d_secsize; - if (lp->d_nsectors == default_label.d_nsectors && - lp->d_ntracks == default_label.d_ntracks && - lp->d_ncylinders == default_label.d_ncylinders) { - /* I guess there is nothing there */ - /* Well, then, Adaptec's like ... */ - dp->dp_sectors = 32; - dp->dp_heads = 64; - dp->dp_cyls = lp->d_secperunit / 64 / 32 ; - } else { - dp->dp_sectors = lp->d_nsectors; - dp->dp_heads = lp->d_ntracks; - dp->dp_cyls = lp->d_ncylinders; - } - - dp->dp_dossectors = 32; - dp->dp_dosheads = 64; - dp->dp_doscyls = lp->d_secperunit / 64 / 32; - dp->dp_ptag = 0; - dp->dp_pflag = 0; -/* !!! partition changes */ -printf("USING PARTIOION TABLE\n"); - dp->dp_pstartsec = lp->d_partitions[part].p_offset; - dp->dp_pnumsec = lp->d_partitions[part].p_size; - *status_count = sizeof(struct disk_parms)/sizeof(int); - break; - } - case V_RDABS: - if (*status_count < DEV_BSIZE/sizeof (int)) { - printf("RDABS bad size %x", *status_count); - return (D_INVALID_OPERATION); - } - if (scsi_rw_abs(dev, status, IO_READ, scsi_abs_sec, DEV_BSIZE) != D_SUCCESS) - return(D_INVALID_OPERATION); - *status_count = DEV_BSIZE/sizeof(int); - break; - case V_VERIFY: { - int count = scsi_abs_count * DEV_BSIZE; - int sec = scsi_abs_sec; - char *scsi_verify_buf; -#include "vm/vm_kern.h" - - (void) kmem_alloc(kernel_map, &scsi_verify_buf, PAGE_SIZE); - - *status = 0; - while (count > 0) { - int xcount = (count < PAGE_SIZE) ? count : PAGE_SIZE; - if (scsi_rw_abs(dev, scsi_verify_buf, IO_READ, sec, xcount) != D_SUCCESS) { - *status = BAD_BLK; - break; - } else { - count -= xcount; - sec += xcount / DEV_BSIZE; - } - } - (void) kmem_free(kernel_map, scsi_verify_buf, PAGE_SIZE); - *status_count = 1; - break; - } - default: - return(D_INVALID_OPERATION); - } - return D_SUCCESS; -} - -io_return_t -scsi_i386_set_status(dev, tgt, flavor, status, status_count) -int dev; -target_info_t *tgt; -int flavor; -int *status; -unsigned int status_count; -{ - io_req_t ior; - - switch (flavor) { - case V_SETPARMS: - printf("scsdisk_set_status: invalid flavor V_SETPARMS\n"); - return(D_INVALID_OPERATION); - break; - case V_REMOUNT: - tgt->flags &= ~TGT_ONLINE; - break; - case V_ABS: - scsi_abs_sec = status[0]; - if (status_count == 2) - scsi_abs_count = status[1]; - break; - case V_WRABS: - if (status_count < DEV_BSIZE/sizeof (int)) { - printf("RDABS bad size %x", status_count); - return (D_INVALID_OPERATION); - } - if (scsi_rw_abs(dev, status, IO_WRITE, scsi_abs_sec, DEV_BSIZE) != D_SUCCESS) - return(D_INVALID_OPERATION); - break; - default: - return(D_INVALID_OPERATION); - } - return D_SUCCESS; -} -#endif /* NSCSI > 0 */ - diff --git a/scsi/rz.c b/scsi/rz.c deleted file mode 100644 index febf629..0000000 --- a/scsi/rz.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1993-1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: rz.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Top layer of the SCSI driver: interface with the MI side. - */ - -/* - * This file contains the code that is common to all scsi devices, - * operations and/or behaviours specific to certain devices live - * in the corresponding rz_mumble files. - */ - -#include <scsi.h> - -#if (NSCSI>0) - -#include <mach/std_types.h> -#include <machine/machspl.h> /* spl definitions */ -#include <scsi/compat_30.h> - -#ifdef MACH_KERNEL -#include <kern/time_out.h> -#else /*MACH_KERNEL*/ -#include <sys/kernel.h> /* for hz */ - -static io_req_t getbp(); -#endif /*MACH_KERNEL*/ - -#include <scsi/scsi_defs.h> -#include <scsi/rz.h> - - -boolean_t -rz_check(dev, p_sc, p_tgt) - int dev; - scsi_softc_t **p_sc; - target_info_t **p_tgt; -{ - if (rzcontroller(dev) >= NSCSI || - (*p_sc = scsi_softc[rzcontroller(dev)]) == 0) - return FALSE; - - *p_tgt = (*p_sc)->target[rzslave(dev)]; - - if (!*p_tgt || - !((*p_tgt)->flags&TGT_ALIVE)) - return FALSE; - return TRUE; -} - -/* - * Open routine - * - * On tapes and other devices might have to wait a bit for - * the unit to come alive. The following patchable variable - * takes this into account - */ -int rz_open_timeout = 60;/* seconds */ - -int rz_open(dev, mode, ior) - int dev; - dev_mode_t mode; - io_req_t ior; -{ - scsi_softc_t *sc = 0; - target_info_t *tgt; - scsi_ret_t ret; - register int i; - - if (!rz_check(dev, &sc, &tgt)) { - /* - * Probe it again: might have installed a new device - */ - if (!sc || !scsi_probe(sc, &tgt, rzslave(dev), ior)) - return D_NO_SUCH_DEVICE; - } - - /* tapes do not wait for rewind to complete on close */ - if (tgt->ior && !(tgt->flags & TGT_ONLINE)) - return D_WOULD_BLOCK; - - if (scsi_debug) - printf("opening %s%d..", (*tgt->dev_ops->driver_name)(TRUE), dev&0xff); - - if (sc->watchdog) { - (*sc->watchdog)(tgt->hw_state); - sc->watchdog = 0; - } - - /* - * Bring the unit online, retrying if necessary. - * If the target is spinning up we wait for it. - */ - if ( ! (tgt->flags & TGT_ONLINE)) { - io_req_t tmp_ior; - - io_req_alloc(tmp_ior,0); - tmp_ior->io_next = 0; - tmp_ior->io_count = 0; - - for (i = 0; i < rz_open_timeout; i++) { - - tmp_ior->io_op = IO_INTERNAL; - tmp_ior->io_error = 0; - ret = scsi_test_unit_ready(tgt, tmp_ior); - - if (ret == SCSI_RET_SUCCESS) - break; - - if (ret == SCSI_RET_DEVICE_DOWN) { - i = rz_open_timeout; - break; - } - - if (ret == SCSI_RET_NEED_SENSE) { - - tmp_ior->io_op = IO_INTERNAL; - tmp_ior->io_count = 0; - tmp_ior->io_residual = 0; - tgt->ior = tmp_ior; - scsi_request_sense(tgt, tmp_ior, 0); - iowait(tmp_ior); - - } - - if (i == 5) printf("%s%d: %s\n", - (*tgt->dev_ops->driver_name)(TRUE), - tgt->target_id, - "Waiting to come online.."); - timeout(wakeup, tgt, hz); - await(tgt); - } - - /* lock on removable media */ - if ((i != rz_open_timeout) && (tgt->flags & TGT_REMOVABLE_MEDIA)) { - tmp_ior->io_op = IO_INTERNAL; - /* too many dont support it. Sigh */ - tgt->flags |= TGT_OPTIONAL_CMD; - (void) scsi_medium_removal( tgt, FALSE, tmp_ior); - tgt->flags &= ~TGT_OPTIONAL_CMD; - } - - io_req_free(tmp_ior); - if (i == rz_open_timeout) - return D_DEVICE_DOWN; - } - /* - * Perform anything open-time special on the device - */ - if (tgt->dev_ops->open != SCSI_OPEN_NULL) { - ret = (*tgt->dev_ops->open)(tgt, ior); - if (ret != SCSI_RET_SUCCESS) { - if (scsi_debug) printf("%s%d: open failed x%x\n", - (*tgt->dev_ops->driver_name)(TRUE), dev&0xff, ret); - return ret; - } - } - tgt->flags |= TGT_ONLINE; - ior->io_device->bsize = tgt->block_size; - return D_SUCCESS; -} - -int rz_close(dev) - int dev; -{ - scsi_softc_t *sc; - target_info_t *tgt; - scsi_ret_t ret; - - if (!rz_check(dev, &sc, &tgt)) - return D_NO_SUCH_DEVICE; - - if (scsi_debug) - printf("closing %s%d..", (*tgt->dev_ops->driver_name)(TRUE), dev&0xff); - - if (tgt->flags & TGT_REMOVABLE_MEDIA) { - io_req_t ior; - - io_req_alloc(ior,0); - ior->io_next = 0; - ior->io_count = 0; - ior->io_op = IO_INTERNAL; - ior->io_error = 0; - /* too many dont support it. Sigh */ - tgt->flags |= TGT_OPTIONAL_CMD; - (void) scsi_medium_removal( tgt, TRUE, ior); - tgt->flags &= ~TGT_OPTIONAL_CMD; - io_req_free(ior); - } - - /* - * Perform anything close-time special on the device - */ - if (tgt->dev_ops->close != SCSI_CLOSE_NULL) { - ret = (*tgt->dev_ops->close)(tgt); - if (ret != SCSI_RET_SUCCESS) { - printf("%s%d: close failed x%x\n", - (*tgt->dev_ops->driver_name)(TRUE), dev&0xff, ret); - } - } - if (tgt->flags & TGT_REMOVABLE_MEDIA) - tgt->flags &= ~TGT_ONLINE; - - return D_SUCCESS; -} - -/* our own minphys */ -void rz_minphys(ior) - io_req_t ior; -{ -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - if (ior->io_count > scsi_per_target_virtual) - ior->io_count = scsi_per_target_virtual; -#endif /*MACH_KERNEL*/ -} - -int rz_read(dev, ior) - int dev; - io_req_t ior; -{ - target_info_t *tgt; - - tgt = scsi_softc[rzcontroller(dev)]->target[rzslave(dev)]; - -#ifdef MACH_KERNEL - return block_io(tgt->dev_ops->strategy, rz_minphys, ior); -#else /*MACH_KERNEL*/ - return physio(tgt->dev_ops->strategy, getbp(dev), dev, IO_READ, rz_minphys, ior); -#endif /*MACH_KERNEL*/ -} - -int rz_write(dev, ior) - int dev; - io_req_t ior; -{ - target_info_t *tgt; - - tgt = scsi_softc[rzcontroller(dev)]->target[rzslave(dev)]; - - if (tgt->flags & TGT_READONLY) - return D_INVALID_OPERATION; - -#ifdef MACH_KERNEL - return block_io(tgt->dev_ops->strategy, rz_minphys, ior); -#else /*MACH_KERNEL*/ - return physio(tgt->dev_ops->strategy, getbp(dev), dev, IO_WRITE, rz_minphys, ior); -#endif /*MACH_KERNEL*/ -} - -int rz_get_status(dev, flavor, status, status_count) - int dev; - dev_flavor_t flavor; - dev_status_t status; - natural_t *status_count; -{ - target_info_t *tgt; - - tgt = scsi_softc[rzcontroller(dev)]->target[rzslave(dev)]; - - if (scsi_debug) - printf("rz_get_status: x%x x%x x%x x%x\n", - dev, flavor, status, *status_count); - return (*tgt->dev_ops->get_status)(dev, tgt, flavor, status, status_count); -} - -int rz_set_status(dev, flavor, status, status_count) - int dev; - dev_flavor_t flavor; - dev_status_t status; - natural_t status_count; -{ - target_info_t *tgt; - - tgt = scsi_softc[rzcontroller(dev)]->target[rzslave(dev)]; - - if (scsi_debug) - printf("rz_set_status: x%x x%x x%x x%x\n", - dev, flavor, status, status_count); - return (*tgt->dev_ops->set_status)(dev, tgt, flavor, status, status_count); -} - -/* - * Routine to return information to kernel. - */ -int -rz_devinfo(dev, flavor, info) - int dev; - int flavor; - char *info; -{ - register int result; - - result = D_SUCCESS; - - switch (flavor) { - /* Caller stupidity, should use device->bsize instead */ - case D_INFO_BLOCK_SIZE: - *((int *) info) = scsi_softc[rzcontroller(dev)]-> - target[rzslave(dev)]->block_size; - break; - default: - result = D_INVALID_OPERATION; - } - - return(result); -} - -void -rz_simpleq_strategy(ior, start) - io_req_t ior; - void (*start)(); -{ - target_info_t *tgt; - register scsi_softc_t *sc; - scsi_ret_t ret; - register int i = ior->io_unit; - io_req_t head, tail; - spl_t s; - - sc = scsi_softc[rzcontroller(i)]; - tgt = sc->target[rzslave(i)]; - - ior->io_next = 0; - ior->io_prev = 0; - - s = splbio(); - simple_lock(&tgt->target_lock); - if (head = tgt->ior) { - /* Queue it up at the end of the list */ - if (tail = head->io_prev) - tail->io_next = ior; - else - head->io_next = ior; - head->io_prev = ior; /* tail pointer */ - simple_unlock(&tgt->target_lock); - } else { - /* Was empty, start operation */ - tgt->ior = ior; - simple_unlock(&tgt->target_lock); - (*start)( tgt, FALSE); - } - splx(s); -} -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - -rz_strategy(ior) - io_req_t ior; -{ - target_info_t *tgt; - register int dev = ior->io_unit; - - tgt = scsi_softc[rzcontroller(dev)]->target[rzslave(dev)]; - - return (*tgt->dev_ops->strategy)(ior); -} - - -#define IOCPARM_SIZE(c) (((c)>>16)&IOCPARM_MASK) -#define IOC_WDSIZE(s) ((IOCPARM_SIZE(s))>>2) - -rz_ioctl(dev, cmd, data, flag) -{ - io_return_t error; - unsigned int count; - - count = IOC_WDSIZE(cmd); - if (cmd & (IOC_VOID|IOC_IN)) { - error = rz_set_status(dev, cmd, (dev_status_t)data, count); - if (error) - return (error); - } - if (cmd & IOC_OUT) { - error = rz_get_status(dev, cmd, (dev_status_t *)data, &count); - if (error) - return (error); - } - return (0); -} - -/* This is a very simple-minded config, - * assumes we have << 8 disks per bus */ -#define NBUF (NSCSI*8) -struct io_req rz_buffers[NBUF]; - -static io_req_t -getbp(dev) -{ - io_req_t ior; - int hash = minor(dev) >> 3; - - ior = &rz_buffers[hash]; - if (ior->io_op & IO_BUSY) { - register io_req_t ior; - for (ior = rz_buffers; ior < &rz_buffers[NBUF]; ior++) - if ((ior->io_op & IO_BUSY) == 0) - return ior; - - } - return ior; -} - -/* - * This ugliness is only needed because of the - * way the minor is encoded for tapes. - */ -tz_open(dev, mode, ior) - int dev; - dev_mode_t mode; - io_req_t ior; -{ - io_return_t error; - - error = rz_open(TAPE_UNIT(dev), mode, ior); - if(error) - return error; - if (TAPE_REWINDS(dev)) { - scsi_softc_t *sc; - target_info_t *tgt; - - rz_check(TAPE_UNIT(dev), &sc, &tgt); - tgt->flags |= TGT_REWIND_ON_CLOSE; - } - return 0; -} - -tz_close(dev) { return rz_close(TAPE_UNIT(dev));} -tz_read(dev, ior) { return rz_read(TAPE_UNIT(dev), ior);} -tz_write(dev, ior) { return rz_write(TAPE_UNIT(dev), ior);} -tz_ioctl(dev, cmd, data, flag) { return rz_ioctl(TAPE_UNIT(dev), cmd, data, flag);} - -#endif /*MACH_KERNEL*/ - -#endif (NSCSI>0) diff --git a/scsi/rz.h b/scsi/rz.h deleted file mode 100644 index 7fa7b88..0000000 --- a/scsi/rz.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: rz.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 9/90 - * - * Mapping between U*x-like indexing and controller+slave - * Each controller handles at most 8 slaves, few controllers. - */ - -#if 0 -#define rzcontroller(dev) (((dev)>>6)&0x3) -#define rzslave(dev) (((dev)>>3)&0x7) -#endif 0 -#define rzcontroller(dev) (((dev)>>13)&0x3) -#define rzslave(dev) (((dev)>>10)&0x7) - -#if 0 -#define rzpartition(dev) ((PARTITION_TYPE(dev)==0xf)?MAXPARTITIONS:((dev)&0x7)) -#endif 0 -#define rzpartition(dev) ((dev)&0x3ff) - -/* To address the full 256 luns use upper bits 8..12 */ -/* NOTE: Under U*x this means the next major up.. what a mess */ -#define rzlun(dev) (((dev)&0x7) | (((dev)>>5)&0xf8)) - -/* note: whatever this was used for is no longer cared about -- Kevin */ -#define PARTITION_TYPE(dev) (((dev)>>24)&0xf) -#define PARTITION_ABSOLUTE (0xf<<24) - -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ -#define tape_unit(dev) ((((dev)&0xe0)>>3)|((dev)&0x3)) -#define TAPE_UNIT(dev) ((dev)&(~0xff))|(tape_unit((dev))<<3) -#define TAPE_REWINDS(dev) (((dev)&0x1c)==0)||(((dev)&0x1c)==8) -#endif /*MACH_KERNEL*/ diff --git a/scsi/rz_audio.c b/scsi/rz_audio.c deleted file mode 100644 index 4d60fa1..0000000 --- a/scsi/rz_audio.c +++ /dev/null @@ -1,1901 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1993 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: rz_audio.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 3/93 - * - * Top layer of the SCSI driver: interface with the MI. - * This file contains operations specific to audio CD-ROM devices. - * Unlike many others, it sits on top of the rz.c module. - */ - -#include <mach/std_types.h> -#include <kern/strings.h> -#include <machine/machspl.h> /* spl definitions */ -#include <vm/vm_kern.h> -#include <device/ds_routines.h> - -#include <scsi/compat_30.h> -#include <scsi/scsi.h> -#include <scsi/scsi2.h> -#include <scsi/scsi_defs.h> -#include <scsi/rz.h> - -#if (NSCSI > 0) - -#define private static - -/* some data is two BCD digits in one byte */ -#define bcd_to_decimal(b) (((b)&0xf) + 10 * (((b) >> 4) & 0xf)) -#define decimal_to_bcd(b) ((((b) / 10) << 4) | ((b) % 10)) - -/* - * Regular use of a CD-ROM is for data, and is handled - * by the default set of operations. Ours is for funtime.. - */ - -extern char *sccdrom_name(); -int cd_strategy(); -void cd_start(); - -private scsi_devsw_t scsi_audio = { - sccdrom_name, 0, 0, 0, cd_strategy, cd_start, 0, 0 -}; - -private char unsupported[] = "Device does not support it."; - -/* - * Unfortunately, none of the vendors appear to - * abide by the SCSI-2 standard and many of them - * violate or stretch even the SCSI-1 one. - * Therefore, we keep a red-list here of the worse - * offendors and how to deal with them. - * The user is notified of the problem and invited - * to solicit his vendor to upgrade the firmware. - * [They had plenty of time to do so] - */ -typedef struct red_list { - char *vendor; - char *product; - char *rev; - /* - * The standard MANDATES [par 13.1.6] the play_audio command - * at least as a way to discover if the device - * supports audio operations at all. This is the only way - * we need to use it. - */ - scsi_ret_t (*can_play_audio)( target_info_t *, char *, io_req_t); - /* - * The standard defines the use of start_stop_unit to - * cause the drive to eject the disk. - */ - scsi_ret_t (*eject)( target_info_t *, char *, io_req_t ); - /* - * The standard defines read_subchannel as a way to - * get the current playing position. - */ - scsi_ret_t (*current_position)( target_info_t *, char *, io_req_t ); - /* - * The standard defines read_table_of_content to get - * the listing of audio tracks available. - */ - scsi_ret_t (*read_toc)( target_info_t *, char *, io_req_t ); - /* - * The standard defines read_subchannel as the way to - * report the current audio status (playing/stopped/...). - */ - scsi_ret_t (*get_status)( target_info_t *, char *, io_req_t ); - /* - * The standard defines two ways to issue a play command, - * depending on the type of addressing used. - */ - scsi_ret_t (*play_msf)( target_info_t *, char *, io_req_t ); - scsi_ret_t (*play_ti)( target_info_t *, char *, io_req_t ); - /* - * The standard defines the pause_resume command to - * suspend or resume playback of audio data. - */ - scsi_ret_t (*pause_resume)( target_info_t *, char *, io_req_t ); - /* - * The standard defines the audio page among the - * mode selection options as a way to control - * both volume and connectivity of the channels - */ - scsi_ret_t (*volume_control)( target_info_t *, char *, io_req_t ); -} red_list_t; - -#define if_it_can_do(some_cmd) \ - if (tgt->dev_info.cdrom.violates_standards && \ - tgt->dev_info.cdrom.violates_standards->some_cmd) \ - rc = (*tgt->dev_info.cdrom.violates_standards->some_cmd) \ - (tgt,cmd,ior); \ - else - -/* - * So now that you know what they should have implemented :-), - * check at the end of the file what the naughty boys did instead. - */ -/* private red_list_t audio_replacements[]; / * at end */ - -/* - * Forward decls - */ -private void decode_status( char *buf, unsigned char audio_status ); -void zero_ior( io_req_t ); - -/* - * Open routine. Does some checking, sets up - * the replacement pointer. - */ -io_return_t -cd_open( - int dev, - dev_mode_t mode, - io_req_t req) -{ - scsi_softc_t *sc = 0; - target_info_t *tgt; - int ret; - scsi_ret_t rc; - io_req_t ior = 0; - vm_offset_t mem = 0; - extern boolean_t rz_check(); - - if (!rz_check(dev, &sc, &tgt)) { - /* - * Probe it again: might have installed a new device - */ - if (!sc || !scsi_probe(sc, &tgt, rzslave(dev), ior)) - return D_NO_SUCH_DEVICE; - bzero(&tgt->dev_info, sizeof(tgt->dev_info)); - } - - /* - * Check this is indeded a CD-ROM - */ - if (tgt->dev_ops != &scsi_devsw[SCSI_CDROM]) { - rz_close(dev); - return D_NO_SUCH_DEVICE; - } - - /* - * Switch to audio ops, unless some wrong - */ - tgt->dev_ops = &scsi_audio; - - /* - * Bring unit online - */ - ret = rz_open(dev, mode, req); - if (ret) goto bad; - - /* Pessimistic */ - ret = D_INVALID_OPERATION; - - /* - * Check if this device is on the red list - */ - { - scsi2_inquiry_data_t *inq; - private void check_red_list(); - - scsi_inquiry(tgt, SCSI_INQ_STD_DATA); - inq = (scsi2_inquiry_data_t*)tgt->cmd_ptr; - - check_red_list( tgt, inq ); - - } - - /* - * Allocate dynamic data - */ - if (kmem_alloc(kernel_map, &mem, PAGE_SIZE) != KERN_SUCCESS) - return D_NO_MEMORY; - tgt->dev_info.cdrom.result = (void *)mem; - tgt->dev_info.cdrom.result_available = FALSE; - - /* - * See if this CDROM can play audio data - */ - io_req_alloc(ior,0); - zero_ior( ior ); - - { - char *cmd = 0; - if_it_can_do(can_play_audio) - rc = scsi_play_audio( tgt, 0, 0, FALSE, ior); - } - - if (rc != SCSI_RET_SUCCESS) goto bad; - - io_req_free(ior); - return D_SUCCESS; - -bad: - if (ior) io_req_free(ior); - if (mem) kmem_free(kernel_map, mem, PAGE_SIZE); - tgt->dev_ops = &scsi_devsw[SCSI_CDROM]; - return ret; -} - -/* - * Close routine. - */ -io_return_t -cd_close( - int dev) -{ - scsi_softc_t *sc; - target_info_t *tgt; - vm_offset_t mem; - - if (!rz_check(dev, &sc, &tgt)) - return D_NO_SUCH_DEVICE; - if (!tgt || (tgt->dev_ops != &scsi_audio)) - return D_NO_SUCH_DEVICE; - - /* - * Cleanup state - */ - mem = (vm_offset_t) tgt->dev_info.cdrom.result; - tgt->dev_info.cdrom.result = (void *)0; - tgt->dev_info.cdrom.result_available = FALSE; - - (void) kmem_free(kernel_map, mem, PAGE_SIZE); - - (void) rz_close(dev); - - tgt->dev_ops = &scsi_devsw[SCSI_CDROM]; - return D_SUCCESS; -} - -/* - * Write routine. It is passed an ASCII string - * with the command to be executed. - */ -io_return_t -cd_write( - int dev, - io_req_t ior) -{ - register kern_return_t rc; - boolean_t wait = FALSE; - io_return_t ret; - int count; - register char *data; - vm_offset_t addr; - - data = ior->io_data; - count = ior->io_count; - if (count == 0) - return D_SUCCESS; - - if (!(ior->io_op & IO_INBAND)) { - /* - * Copy out-of-line data into kernel address space. - * Since data is copied as page list, it will be - * accessible. - */ - vm_map_copy_t copy = (vm_map_copy_t) data; - kern_return_t kr; - - kr = vm_map_copyout(device_io_map, &addr, copy); - if (kr != KERN_SUCCESS) - return kr; - data = (char *) addr; - } - - if (scsi_debug) printf("Got command '%s'\n", data); - - ret = cd_command( dev, data, count, ior); - - if (!(ior->io_op & IO_INBAND)) - (void) vm_deallocate(device_io_map, addr, ior->io_count); - return D_SUCCESS; -} - -/* - * Read routine. Returns an ASCII string with the results - * of the last command executed. - */ -io_return_t -cd_read( - int dev, - io_req_t ior) -{ - target_info_t *tgt; - kern_return_t rc; - natural_t count; - - /* - * Allocate memory for read buffer. - */ - count = (natural_t)ior->io_count; - if (count > PAGE_SIZE) - return D_INVALID_SIZE; /* sanity */ - - rc = device_read_alloc(ior, count); - if (rc != KERN_SUCCESS) - return rc; - - if (scsi_debug) printf("Got read req for %d bytes\n", count); - - /* - * See if last cmd left some to say - */ - tgt = scsi_softc[rzcontroller(dev)]->target[rzslave(dev)]; - if (tgt->dev_info.cdrom.result_available) { - int len; - - tgt->dev_info.cdrom.result_available = FALSE; - len = strlen(tgt->dev_info.cdrom.result)+1; - - if (count > len) - count = len; - bcopy(tgt->dev_info.cdrom.result, ior->io_data, count); - - } else { -# define noway "No results pending" - count = (count > sizeof(noway)) ? sizeof(noway) : count; - bcopy(noway, ior->io_data, count); - } - - ior->io_residual = ior->io_count - count; - return D_SUCCESS; -} - -/* - * This does all the work - */ -io_return_t -cd_command( - int dev, - char *cmd, - int count, - io_req_t req) -{ - target_info_t *tgt; - io_req_t ior; - io_return_t ret = D_INVALID_OPERATION; - scsi_ret_t rc; - char *buf; - - tgt = scsi_softc[rzcontroller(dev)]->target[rzslave(dev)]; - - buf = tgt->dev_info.cdrom.result; - tgt->dev_info.cdrom.result_available = FALSE; - - io_req_alloc(ior,0); - zero_ior( ior ); - - switch (cmd[0]) { - - case 'E': - /* "Eject" */ - /* too many dont support it. Sigh */ - tgt->flags |= TGT_OPTIONAL_CMD; - (void) scsi_medium_removal( tgt, TRUE, ior); - tgt->flags &= ~TGT_OPTIONAL_CMD; - - zero_ior( ior ); - - if_it_can_do(eject) - rc = scsi_start_unit(tgt, SCSI_CMD_SS_EJECT, ior); - break; - - case 'G': - switch (cmd[4]) { - - case 'P': - /* "Get Position MSF|ABS" */ - if_it_can_do(current_position) { - rc = scsi_read_subchannel(tgt, - cmd[13] == 'M', - SCSI_CMD_RS_FMT_CURPOS, - 0, - ior); - if (rc == SCSI_RET_SUCCESS) { - cdrom_chan_curpos_t *st; - st = (cdrom_chan_curpos_t *)tgt->cmd_ptr; - if (cmd[13] == 'M') - sprintf(buf, "MSF Position %d %d %d %d %d %d", - (integer_t)st->subQ.absolute_address.msf.minute, - (integer_t)st->subQ.absolute_address.msf.second, - (integer_t)st->subQ.absolute_address.msf.frame, - (integer_t)st->subQ.relative_address.msf.minute, - (integer_t)st->subQ.relative_address.msf.second, - (integer_t)st->subQ.relative_address.msf.frame); - else - sprintf(buf, "ABS Position %d %d", (integer_t) - (st->subQ.absolute_address.lba.lba1<<24)+ - (st->subQ.absolute_address.lba.lba2<<16)+ - (st->subQ.absolute_address.lba.lba3<< 8)+ - st->subQ.absolute_address.lba.lba4, - (integer_t) - (st->subQ.relative_address.lba.lba1<<24)+ - (st->subQ.relative_address.lba.lba2<<16)+ - (st->subQ.relative_address.lba.lba3<< 8)+ - st->subQ.relative_address.lba.lba4); - tgt->dev_info.cdrom.result_available = TRUE; - } - } - break; - - case 'T': - /* "Get TH" */ - if_it_can_do(read_toc) { - rc = scsi_read_toc(tgt, TRUE, 1, PAGE_SIZE, ior); - if (rc == SCSI_RET_SUCCESS) { - cdrom_toc_t *toc = (cdrom_toc_t *)tgt->cmd_ptr; - sprintf(buf, "toc header: %d %d %d", - (toc->len1 << 8) + toc->len2, - toc->first_track, - toc->last_track); - tgt->dev_info.cdrom.result_available = TRUE; - } - } - break; - - case 'S': - /* "Get Status" */ - if_it_can_do(get_status) { - rc = scsi_read_subchannel(tgt, - TRUE, - SCSI_CMD_RS_FMT_CURPOS, - 0, - ior); - if (rc == SCSI_RET_SUCCESS) { - cdrom_chan_curpos_t *st; - st = (cdrom_chan_curpos_t *)tgt->cmd_ptr; - decode_status(buf, st->audio_status); - tgt->dev_info.cdrom.result_available = TRUE; - } - } - break; - } - break; - - case 'P': - switch (cmd[5]) { - case 'A': - /* "Play A startM startS startF endM endS endF" */ - if_it_can_do(play_msf) { - - int sm, ss, sf, em, es, ef; - - sscanf(&cmd[7], "%d %d %d %d %d %d", - &sm, &ss, &sf, &em, &es, &ef); - - rc = scsi_play_audio_msf(tgt, - sm, ss, sf, - em, es, ef, - ior); - } - break; - - case 'T': - /* "Play TI startT startI endT endI" */ - if_it_can_do(play_ti) { - - int st, si, et, ei; - - sscanf(&cmd[8], "%d %d %d %d", - &st, &si, &et, &ei); - - rc = scsi_play_audio_track_index(tgt, - st, si, et, ei, ior); - } - break; - } - break; - - case 'R': - /* "Resume" */ - if_it_can_do(pause_resume) - rc = scsi_pause_resume(tgt, FALSE, ior); - break; - - case 'S': - switch (cmd[2]) { - - case 'a': - /* "Start" */ - rc = scsi_start_unit(tgt, SCSI_CMD_SS_START, ior); - break; - - case 'o': - /* "Stop" */ - if_it_can_do(pause_resume) - rc = scsi_pause_resume(tgt, TRUE, ior); - break; - - case 't': - /* "Set V chan0vol chan1vol chan2vol chan3vol" */ - if_it_can_do(volume_control) { - - int v0, v1, v2, v3; - cdrom_audio_page_t au, *aup; - - rc = scsi_mode_sense(tgt, - SCSI_CD_AUDIO_PAGE, - sizeof(au), - ior); - if (rc == SCSI_RET_SUCCESS) { - - sscanf(&cmd[6], "%d %d %d %d", - &v0, &v1, &v2, &v3); - - aup = (cdrom_audio_page_t *) tgt->cmd_ptr; - au = *aup; - /* au.h.bdesc ... */ - au.vol0 = v0; - au.vol1 = v1; - au.vol2 = v2; - au.vol3 = v3; - au.imm = 1; - au.aprv = 0; - - zero_ior( ior ); - - rc = scsi2_mode_select(tgt, FALSE, - &au, sizeof(au), ior); - } - } - break; - } - break; - - case 'T': - /* "Toc MSF|ABS trackno" */ - if_it_can_do(read_toc) { - - int t, m; - - sscanf(&cmd[8], "%d", &t); - rc = scsi_read_toc( tgt, cmd[4]=='M', t, PAGE_SIZE, ior); - - if (rc == SCSI_RET_SUCCESS) { - - cdrom_toc_t *toc = (cdrom_toc_t *)tgt->cmd_ptr; - - sprintf(buf, "TOC from track %d:\n", t); - m = (toc->len1 << 8) + toc->len2; - m -= 4; /* header */ - for (t = 0; m > 0; t++, m -= sizeof(struct cdrom_toc_desc)) { - buf += strlen(buf); - if (cmd[4] == 'M') - sprintf(buf, "%d %d %d %d %d %d\n", - toc->descs[t].control, - toc->descs[t].adr, - toc->descs[t].trackno, - (integer_t)toc->descs[t].absolute_address.msf.minute, - (integer_t)toc->descs[t].absolute_address.msf.second, - (integer_t)toc->descs[t].absolute_address.msf.frame); - else - sprintf(buf, "%d %d %d %d\n", - toc->descs[t].control, - toc->descs[t].adr, - toc->descs[t].trackno, - (toc->descs[t].absolute_address.lba.lba1<<24)+ - (toc->descs[t].absolute_address.lba.lba2<<16)+ - (toc->descs[t].absolute_address.lba.lba3<<8)+ - toc->descs[t].absolute_address.lba.lba4); - } - tgt->dev_info.cdrom.result_available = TRUE; - } - } - break; - } - - if (rc == SCSI_RET_SUCCESS) - ret = D_SUCCESS; - - /* We are stateless, but.. */ - if (rc == SCSI_RET_NEED_SENSE) { - zero_ior( ior ); - tgt->ior = ior; - scsi_request_sense(tgt, ior, 0); - iowait(ior); - if (scsi_check_sense_data(tgt, tgt->cmd_ptr)) - scsi_print_sense_data(tgt->cmd_ptr); - } - - io_req_free(ior); - return ret; -} - -private char st_invalid [] = "Drive would not say"; -private char st_playing [] = "Playing"; -private char st_paused [] = "Suspended"; -private char st_complete[] = "Done playing"; -private char st_error [] = "Stopped in error"; -private char st_nothing [] = "Idle"; - -private void -decode_status( - char *buf, - unsigned char audio_status) -{ - switch (audio_status) { - case SCSI_CDST_INVALID: - sprintf(buf, st_invalid); break; - case SCSI_CDST_PLAYING: - sprintf(buf, st_playing); break; - case SCSI_CDST_PAUSED: - sprintf(buf, st_paused); break; - case SCSI_CDST_COMPLETED: - sprintf(buf, st_complete); break; - case SCSI_CDST_ERROR: - sprintf(buf, st_error); break; - case SCSI_CDST_NO_STATUS: - sprintf(buf, st_nothing); break; - } -} - -/* some vendor specific use this instead */ -private void -decode_status_1( - char *buf, - unsigned char audio_status) -{ - switch (audio_status) { - case 0: sprintf(buf, st_playing ); break; - case 1: - case 2: sprintf(buf, st_paused ); break; - case 3: sprintf(buf, st_complete ); break; - default: - sprintf(buf, "Unknown status" ); break; - } -} - - -private void -curse_the_vendor( - red_list_t *list, - boolean_t not_really) -{ - if (not_really) return; - - printf("%s\n%s\n%s\n%s\n", - "The CDROM you use is not fully SCSI-2 compliant.", - "We invite You to contact Your vendor and ask", - "that they provide You with a firmware upgrade.", - "Here is a list of some known deficiencies"); - - printf("Vendor: %s Product: %s.. Revision: %s..\n", - list->vendor, list->product, list->rev); - -#define check(x,y,z) \ - if (list->x) printf("Command code x%x %s not supported\n", y, z); - - check(can_play_audio, SCSI_CMD_PLAY_AUDIO, "PLAY_AUDIO"); - check(eject, SCSI_CMD_START_STOP_UNIT, - "START_STOP_UNIT, flag EJECT(0x2) in byte 5"); - check(current_position, SCSI_CMD_READ_SUBCH, "READ_SUBCHANNEL"); - check(read_toc, SCSI_CMD_READ_TOC, "READ_TOC"); -/* check(get_status, ...); duplicate of current_position */ - check(play_msf, SCSI_CMD_PLAY_AUDIO_MSF, "PLAY_AUDIO_MSF"); - check(play_ti, SCSI_CMD_PLAY_AUDIO_TI, "PLAY_AUDIO_TRACK_INDEX"); - check(pause_resume, SCSI_CMD_PAUSE_RESUME, "PAUSE_RESUME"); - check(volume_control, SCSI_CMD_MODE_SELECT, - "MODE_SELECT, AUDIO page(0xe)"); - -#undef check - printf("Will work around these problems...\n"); -} - -/* - * Ancillaries - */ -cd_strategy(ior) - register io_req_t ior; -{ - return rz_simpleq_strategy( ior, cd_start); -} - -void cd_start( tgt, done) - target_info_t *tgt; - boolean_t done; -{ - io_req_t ior; - - ior = tgt->ior; - if (done && ior) { - tgt->ior = 0; - iodone(ior); - return; - } - panic("cd start"); /* uhu? */ -} - -/* - * When the hardware cannot - */ -private scsi_ret_t -op_not_supported( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - /* - * The command is not implemented, no way around it - */ - sprintf(tgt->dev_info.cdrom.result, unsupported); - tgt->dev_info.cdrom.result_available = TRUE; - return SCSI_RET_SUCCESS; -} - -/****************************************/ -/* Vendor Specific Operations */ -/****************************************/ - - /* DEC RRD42 */ - -#define SCSI_CMD_DEC_SET_ADDRESS_FORMAT 0xc0 -# define scsi_cmd_saf_fmt scsi_cmd_xfer_len_2 - -#define SCSI_CMD_DEC_PLAYBACK_STATUS 0xc4 -typedef struct { - unsigned char xxx; - BITFIELD_2(unsigned char, - is_msf: 1, - xxx1: 7); - unsigned char data_len1; - unsigned char data_len0; - unsigned char audio_status; - BITFIELD_2(unsigned char, - control : 4, - xxx2 : 4); - cdrom_addr_t address; - BITFIELD_2(unsigned char, - chan0_select : 4, - xxx3 : 4); - unsigned char chan0_volume; - BITFIELD_2(unsigned char, - chan1_select : 4, - xxx4 : 4); - unsigned char chan1_volume; - BITFIELD_2(unsigned char, - chan2_select : 4, - xxx5 : 4); - unsigned char chan2_volume; - BITFIELD_2(unsigned char, - chan3_select : 4, - xxx6 : 4); - unsigned char chan3_volume; -} dec_playback_status_t; - -#define SCSI_CMD_DEC_PLAYBACK_CONTROL 0xc9 -typedef struct { - unsigned char xxx0; - BITFIELD_2(unsigned char, - fmt : 1, - xxx1 : 7); - unsigned char xxx[8]; - BITFIELD_2(unsigned char, - chan0_select : 4, - xxx3 : 4); - unsigned char chan0_volume; - BITFIELD_2(unsigned char, - chan1_select : 4, - xxx4 : 4); - unsigned char chan1_volume; - BITFIELD_2(unsigned char, - chan2_select : 4, - xxx5 : 4); - unsigned char chan2_volume; - BITFIELD_2(unsigned char, - chan3_select : 4, - xxx6 : 4); - unsigned char chan3_volume; -} dec_playback_control_t; - - -#if 0 - -private scsi_ret_t -rrd42_status( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_ret_t rc; - char *buf = tgt->dev_info.cdrom.result; - scsi_command_group_2 c; - dec_playback_status_t *st; - - /* We might have to specify addressing fmt */ - if (cmd[4] == 'P') { - scsi_command_group_2 saf; - - bzero(&saf, sizeof(saf)); - saf.scsi_cmd_code = SCSI_CMD_DEC_SET_ADDRESS_FORMAT; - saf.scsi_cmd_saf_fmt = (cmd[13] == 'A') ? 0 : 1; - - rc = cdrom_vendor_specific(tgt, &saf, 0, 0, 0, ior); - - if (rc != SCSI_RET_SUCCESS) return rc; - - zero_ior( ior ); - } - - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_DEC_PLAYBACK_STATUS; - c.scsi_cmd_xfer_len_2 = sizeof(*st); - rc = cdrom_vendor_specific(tgt, &c, 0, 0, sizeof(*st), ior); - - if (rc != SCSI_RET_SUCCESS) return rc; - - st = (dec_playback_status_t *) tgt->cmd_ptr; - - if (cmd[4] == 'S') - decode_status( buf, st->audio_status+0x11 ); - else { - if (st->is_msf) - sprintf(buf, "MSF Position %d %d %d", - (integer_t)st->address.msf.minute, - (integer_t)st->address.msf.second, - (integer_t)st->address.msf.frame); - else - sprintf(buf, "ABS Position %d", (integer_t) - (st->address.lba.lba1<<24)+ - (st->address.lba.lba2<<16)+ - (st->address.lba.lba3<< 8)+ - st->address.lba.lba4); - } - tgt->dev_info.cdrom.result_available = TRUE; - return rc; -} -#endif - -private scsi_ret_t -rrd42_set_volume( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - dec_playback_control_t req; - int v0, v1, v2, v3; - - sscanf(&cmd[6], "%d %d %d %d", &v0, &v1, &v2, &v3); - - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_DEC_PLAYBACK_CONTROL; - c.scsi_cmd_xfer_len_2 = sizeof(req); - bzero(&req, sizeof(req)); - if (v0) { - req.chan0_select = 1; - req.chan0_volume = v0; - } - if (v1) { - req.chan1_select = 2; - req.chan1_volume = v1; - } - if (v2) { - req.chan2_select = 4; - req.chan2_volume = v2; - } - if (v3) { - req.chan3_select = 8; - req.chan3_volume = v3; - } - return cdrom_vendor_specific(tgt, &c, &req, sizeof(req), 0, ior); -} - - /* NEC CD-ROM */ - -#define SCSI_CMD_NEC_READ_TOC 0xde -typedef struct { - unsigned char xxx[9]; - unsigned char first_track; - unsigned char xxx1[9]; - unsigned char last_track; - unsigned char xxx2[9]; - unsigned char lead_out_addr[3]; - struct { - BITFIELD_2(unsigned char, - adr : 4, - ctrl : 4); - unsigned char xxx3[6]; - unsigned char address[3]; - } track_info[1]; /* VARSIZE */ -} nec_toc_data_t; - -#define SCSI_CMD_NEC_SEEK_TRK 0xd8 -#define SCSI_CMD_NEC_PLAY_AUDIO 0xd9 -#define SCSI_CMD_NEC_PAUSE 0xda -#define SCSI_CMD_NEC_EJECT 0xdc - -#define SCSI_CMD_NEC_READ_SUBCH_Q 0xdd -typedef struct { - unsigned char audio_status; /* see decode_status_1 */ - BITFIELD_2(unsigned char, - ctrl : 4, - xxx1 : 4); - unsigned char trackno; - unsigned char indexno; - unsigned char relative_address[3]; - unsigned char absolute_address[3]; -} nec_subch_data_t; - -/* - * Reserved bits in byte1 - */ -#define NEC_LR_PLAY_MODE 0x01 /* RelAdr bit overload */ -#define NEC_LR_STEREO 0x02 /* mono/stereo */ - -/* - * Vendor specific bits in the control byte. - * NEC uses them to specify the addressing mode - */ -#define NEC_CTRL_A_ABS 0x00 /* XXX not sure about this */ -#define NEC_CTRL_A_MSF 0x40 /* min/sec/frame */ -#define NEC_CTRL_A_TI 0x80 /* track/index */ -#define NEC_CTRL_A_CURRENT 0xc0 /* same as last specified */ - -private scsi_ret_t -nec_eject( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_NEC_EJECT; - - return cdrom_vendor_specific(tgt, &c, 0, 0, 0, ior); -} - -private scsi_ret_t -nec_subchannel( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - nec_subch_data_t *st; - char *buf = tgt->dev_info.cdrom.result; - scsi_ret_t rc; - - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_NEC_READ_SUBCH_Q; - c.scsi_cmd_lun_and_relbit = sizeof(*st); /* Sic! */ - - rc = cdrom_vendor_specific(tgt, &c, 0, 0, sizeof(*st), ior); - if (rc != SCSI_RET_SUCCESS) return rc; - - st = (nec_subch_data_t *) tgt->cmd_ptr; - - /* Status or Position ? */ - - if (cmd[4] == 'S') { - decode_status_1( buf, st->audio_status); - } else { - - /* XXX can it do ABS addressing e.g. 'logical' ? */ - - sprintf(buf, "MSF Position %d %d %d %d %d %d", - (integer_t)bcd_to_decimal(st->absolute_address[0]), /* min */ - (integer_t)bcd_to_decimal(st->absolute_address[1]), /* sec */ - (integer_t)bcd_to_decimal(st->absolute_address[2]), /* frm */ - (integer_t)bcd_to_decimal(st->relative_address[0]), /* min */ - (integer_t)bcd_to_decimal(st->relative_address[1]), /* sec */ - (integer_t)bcd_to_decimal(st->relative_address[2])); /* frm */ - } - - tgt->dev_info.cdrom.result_available = TRUE; - return SCSI_RET_SUCCESS; -} - -private scsi_ret_t -nec_read_toc( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - nec_toc_data_t *t; - char *buf = tgt->dev_info.cdrom.result; - scsi_ret_t rc; - int first, last, i; - - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_NEC_READ_TOC; - c.scsi_cmd_lun_and_relbit = NEC_LR_PLAY_MODE|NEC_LR_STEREO; - - rc = cdrom_vendor_specific(tgt, &c, 0, 0, 512/*XXX*/, ior); - if (rc != SCSI_RET_SUCCESS) return rc; - - t = (nec_toc_data_t *) tgt->cmd_ptr; - - first = bcd_to_decimal(t->first_track); - last = bcd_to_decimal(t->last_track); - - /* - * "Get TH" wants summary, "TOC MSF|ABS from_track" wants all - */ - if (cmd[0] == 'G') { - sprintf(buf, "toc header: %d %d %d", - sizeof(*t) + sizeof(t->track_info) * (last - first - 1), - first, last); - goto out; - } - - /* - * The whole shebang - */ - sscanf(&cmd[8], "%d", &i); - sprintf(buf, "TOC from track %d:\n", i); - - last -= first; - i -= first; - while ((i >= 0) && (i <= last)) { - buf += strlen(buf); - if (cmd[4] == 'M') - sprintf(buf, "%d %d %d %d %d %d\n", - t->track_info[i].ctrl, - t->track_info[i].adr, - first + i, - bcd_to_decimal(t->track_info[i].address[0]), - bcd_to_decimal(t->track_info[i].address[1]), - bcd_to_decimal(t->track_info[i].address[2])); - else -/* THIS IS WRONG */ - sprintf(buf, "%d %d %d %d\n", - t->track_info[i].ctrl, - t->track_info[i].adr, - first + i, - bcd_to_decimal(t->track_info[i].address[0]) * 10000 + - bcd_to_decimal(t->track_info[i].address[1]) * 100 + - bcd_to_decimal(t->track_info[i].address[2])); - i++; - } - /* To know how long the last track is */ - buf += strlen(buf); - if (cmd[4] == 'M') - sprintf(buf, "%d %d %d %d %d %d\n", - 0, 1, 0xaa /* User expects this */, - bcd_to_decimal(t->lead_out_addr[0]), - bcd_to_decimal(t->lead_out_addr[1]), - bcd_to_decimal(t->lead_out_addr[2])); - else -/* THIS IS WRONG */ - sprintf(buf, "%d %d %d %d\n", - 0, 1, 0xaa /* User expects this */, - bcd_to_decimal(t->lead_out_addr[0]) * 10000 + - bcd_to_decimal(t->lead_out_addr[1]) * 100 + - bcd_to_decimal(t->lead_out_addr[2])); -out: - tgt->dev_info.cdrom.result_available = TRUE; - return SCSI_RET_SUCCESS; -} - - -private scsi_ret_t -nec_play( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - int sm, ss, sf, em, es, ef; - int st, si, et, ei; - scsi_ret_t rc; - - /* - * Seek to desired position - */ - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_NEC_SEEK_TRK; - c.scsi_cmd_lun_and_relbit = NEC_LR_PLAY_MODE; - - /* - * Play_msf or Play_ti - */ - if (cmd[5] == 'A') { - /* "Play A startM startS startF endM endS endF" */ - - sscanf(&cmd[7], "%d %d %d %d %d %d", - &sm, &ss, &sf, &em, &es, &ef); - - c.scsi_cmd_lba1 = decimal_to_bcd(sm); - c.scsi_cmd_lba2 = decimal_to_bcd(ss); - c.scsi_cmd_lba3 = decimal_to_bcd(sf); - c.scsi_cmd_ctrl_byte = NEC_CTRL_A_MSF; - - } else { - /* "Play TI startT startI endT endI" */ - - sscanf(&cmd[8], "%d %d %d %d", &st, &si, &et, &ei); - - c.scsi_cmd_lba1 = decimal_to_bcd(st); - c.scsi_cmd_lba2 = decimal_to_bcd(si); - c.scsi_cmd_lba3 = 0; - c.scsi_cmd_ctrl_byte = NEC_CTRL_A_TI; - - } - - rc = cdrom_vendor_specific(tgt, &c, 0, 0, 0, ior); - if (rc != SCSI_RET_SUCCESS) return rc; - - /* - * Now ask it to play until.. - */ - zero_ior( ior ); - - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_NEC_PLAY_AUDIO; - c.scsi_cmd_lun_and_relbit = NEC_LR_PLAY_MODE|NEC_LR_STEREO; - - if (cmd[5] == 'A') { - c.scsi_cmd_lba1 = decimal_to_bcd(em); - c.scsi_cmd_lba2 = decimal_to_bcd(es); - c.scsi_cmd_lba3 = decimal_to_bcd(ef); - c.scsi_cmd_ctrl_byte = NEC_CTRL_A_MSF; - } else { - c.scsi_cmd_lba1 = decimal_to_bcd(et); - c.scsi_cmd_lba2 = decimal_to_bcd(ei); - c.scsi_cmd_lba3 = 0; - c.scsi_cmd_ctrl_byte = NEC_CTRL_A_TI; - } - - return cdrom_vendor_specific(tgt, &c, 0, 0, 0, ior); -} - -private scsi_ret_t -nec_pause_resume( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - - bzero(&c, sizeof(c)); - /* - * "Resume" or "Stop" - */ - if (cmd[0] == 'R') { - c.scsi_cmd_code = SCSI_CMD_NEC_PLAY_AUDIO; - c.scsi_cmd_lun_and_relbit = NEC_LR_PLAY_MODE|NEC_LR_STEREO; - c.scsi_cmd_ctrl_byte = NEC_CTRL_A_CURRENT; - } else { - c.scsi_cmd_code = SCSI_CMD_NEC_PAUSE; - } - - return cdrom_vendor_specific(tgt, &c, 0, 0, 0, ior); -} - - /* TOSHIBA CD-ROM DRIVE:XM 3232 */ - -#define SCSI_CMD_TOSHIBA_SEEK_TRK 0xc0 -#define SCSI_CMD_TOSHIBA_PLAY_AUDIO 0xc1 -#define SCSI_CMD_TOSHIBA_PAUSE_AUDIO 0xc2 -#define SCSI_CMD_TOSHIBA_EJECT 0xc4 - -#define SCSI_CMD_TOSHIBA_READ_SUBCH_Q 0xc6 -typedef nec_subch_data_t toshiba_subch_data_t; -/* audio status -> decode_status_1 */ - -#define SCSI_CMD_TOSHIBA_READ_TOC_ENTRY 0xc7 -typedef struct { - unsigned char first_track; - unsigned char last_track; - unsigned char xxx[2]; -} toshiba_toc_header_t; -typedef struct { - unsigned char address[4]; -} toshiba_toc_data_t; - - -private scsi_ret_t -toshiba_eject( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_TOSHIBA_EJECT; - - return cdrom_vendor_specific(tgt, &c, 0, 0, 0, ior); -} - -private scsi_ret_t -toshiba_subchannel( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - toshiba_subch_data_t *st; - char *buf = tgt->dev_info.cdrom.result; - scsi_ret_t rc; - - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_TOSHIBA_READ_SUBCH_Q; - c.scsi_cmd_lun_and_relbit = sizeof(*st); /* Sic! */ - - rc = cdrom_vendor_specific(tgt, &c, 0, 0, sizeof(*st), ior); - if (rc != SCSI_RET_SUCCESS) return rc; - - st = (toshiba_subch_data_t *) tgt->cmd_ptr; - - /* Status or Position ? */ - - if (cmd[4] == 'S') { - decode_status_1( buf, st->audio_status); - } else { - - /* XXX can it do ABS addressing e.g. 'logical' ? */ - - sprintf(buf, "MSF Position %d %d %d %d %d %d", - (integer_t)bcd_to_decimal(st->absolute_address[0]), /* min */ - (integer_t)bcd_to_decimal(st->absolute_address[1]), /* sec */ - (integer_t)bcd_to_decimal(st->absolute_address[2]), /* frm */ - (integer_t)bcd_to_decimal(st->relative_address[0]), /* min */ - (integer_t)bcd_to_decimal(st->relative_address[1]), /* sec */ - (integer_t)bcd_to_decimal(st->relative_address[2])); /* frm */ - } - - tgt->dev_info.cdrom.result_available = TRUE; - return SCSI_RET_SUCCESS; -} - -private scsi_ret_t -toshiba_read_toc( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - toshiba_toc_data_t *t; - toshiba_toc_header_t *th; - char *buf = tgt->dev_info.cdrom.result; - scsi_ret_t rc; - int first, last, i; - - /* TOC header first */ - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_TOSHIBA_READ_TOC_ENTRY; - c.scsi_cmd_lun_and_relbit = 0; - c.scsi_cmd_lba1 = 0; - - rc = cdrom_vendor_specific(tgt, &c, 0, 0, sizeof(*th), ior); - if (rc != SCSI_RET_SUCCESS) return rc; - - th = (toshiba_toc_header_t *) tgt->cmd_ptr; - - first = bcd_to_decimal(th->first_track); - last = bcd_to_decimal(th->last_track); - - /* - * "Get TH" wants summary, "TOC MSF|ABS from_track" wants all - */ - if (cmd[0] == 'G') { - sprintf(buf, "toc header: %d %d %d", - sizeof(*th) + sizeof(*t) * (last - first + 1), - first, last); - goto out; - } - - /* - * The whole shebang - */ - sscanf(&cmd[8], "%d", &i); - sprintf(buf, "TOC from track %d:\n", i); - - while (i <= last) { - bzero(&c, sizeof(c)); - - c.scsi_cmd_code = SCSI_CMD_TOSHIBA_READ_TOC_ENTRY; - c.scsi_cmd_lun_and_relbit = 2; - c.scsi_cmd_lba1 = decimal_to_bcd(i); - - zero_ior( ior ); - rc = cdrom_vendor_specific(tgt, &c, 0, 0, sizeof(*t), ior); - if (rc != SCSI_RET_SUCCESS) break; - - t = (toshiba_toc_data_t *) tgt->cmd_ptr; - - buf += strlen(buf); - if (cmd[4] == 'M') - sprintf(buf, "0 0 %d %d %d %d\n", - i, - bcd_to_decimal(t->address[0]), - bcd_to_decimal(t->address[1]), - bcd_to_decimal(t->address[2])); - else -/* THIS IS WRONG */ - sprintf(buf, "0 0 %d %d\n", - i, - bcd_to_decimal(t->address[0]) * 10000 + - bcd_to_decimal(t->address[1]) * 100 + - bcd_to_decimal(t->address[2])); - i++; - } - - /* Must simulate the lead-out track */ - bzero(&c, sizeof(c)); - - c.scsi_cmd_code = SCSI_CMD_TOSHIBA_READ_TOC_ENTRY; - c.scsi_cmd_lun_and_relbit = 1; - c.scsi_cmd_lba1 = 0; - - zero_ior( ior ); - rc = cdrom_vendor_specific(tgt, &c, 0, 0, sizeof(*t), ior); - if (rc != SCSI_RET_SUCCESS) goto out; - - t = (toshiba_toc_data_t *) tgt->cmd_ptr; - - buf += strlen(buf); - if (cmd[4] == 'M') - sprintf(buf, "0 0 %d %d %d %d\n", - i, - bcd_to_decimal(t->address[0]), - bcd_to_decimal(t->address[1]), - bcd_to_decimal(t->address[2])); - else -/* THIS IS WRONG */ - sprintf(buf, "0 0 %d %d\n", - i, - bcd_to_decimal(t->address[0]) * 10000 + - bcd_to_decimal(t->address[1]) * 100 + - bcd_to_decimal(t->address[2])); - i++; - -out: - tgt->dev_info.cdrom.result_available = TRUE; - return SCSI_RET_SUCCESS; -} - - -private scsi_ret_t -toshiba_play( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - int sm, ss, sf, em, es, ef; - int st, si, et, ei; - scsi_ret_t rc; - - /* - * Seek to desired position - */ - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_TOSHIBA_SEEK_TRK; - - /* - * Play_msf or Play_ti - */ - if (cmd[5] == 'A') { - /* "Play A startM startS startF endM endS endF" */ - - sscanf(&cmd[7], "%d %d %d %d %d %d", - &sm, &ss, &sf, &em, &es, &ef); - - c.scsi_cmd_lba1 = decimal_to_bcd(sm); - c.scsi_cmd_lba2 = decimal_to_bcd(ss); - c.scsi_cmd_lba3 = decimal_to_bcd(sf); - c.scsi_cmd_ctrl_byte = NEC_CTRL_A_MSF; - - } else { - /* "Play TI startT startI endT endI" */ - - sscanf(&cmd[8], "%d %d %d %d", &st, &si, &et, &ei); - - c.scsi_cmd_lba1 = decimal_to_bcd(st); - c.scsi_cmd_lba2 = decimal_to_bcd(si); - c.scsi_cmd_lba3 = 0; - c.scsi_cmd_ctrl_byte = NEC_CTRL_A_TI; - - } - - rc = cdrom_vendor_specific(tgt, &c, 0, 0, 0, ior); - if (rc != SCSI_RET_SUCCESS) return rc; - - /* - * Now ask it to play until.. - */ - zero_ior( ior ); - - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_TOSHIBA_PLAY_AUDIO; - c.scsi_cmd_lun_and_relbit = NEC_LR_PLAY_MODE|NEC_LR_STEREO; - - if (cmd[5] == 'A') { - c.scsi_cmd_lba1 = decimal_to_bcd(em); - c.scsi_cmd_lba2 = decimal_to_bcd(es); - c.scsi_cmd_lba3 = decimal_to_bcd(ef); - c.scsi_cmd_ctrl_byte = NEC_CTRL_A_MSF; - } else { - c.scsi_cmd_lba1 = decimal_to_bcd(et); - c.scsi_cmd_lba2 = decimal_to_bcd(ei); - c.scsi_cmd_lba3 = 0; - c.scsi_cmd_ctrl_byte = NEC_CTRL_A_TI; - } - - return cdrom_vendor_specific(tgt, &c, 0, 0, 0, ior); -} - -private scsi_ret_t -toshiba_pause_resume( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - - bzero(&c, sizeof(c)); - /* - * "Resume" or "Stop" - */ - if (cmd[0] == 'R') { - /* ???? would have to remember last cmd ???? */ -/* broken ! */ - c.scsi_cmd_code = SCSI_CMD_TOSHIBA_PLAY_AUDIO; - c.scsi_cmd_lun_and_relbit = NEC_LR_PLAY_MODE|NEC_LR_STEREO; - c.scsi_cmd_ctrl_byte = NEC_CTRL_A_CURRENT; - } else { - c.scsi_cmd_code = SCSI_CMD_TOSHIBA_PAUSE_AUDIO; - } - - return cdrom_vendor_specific(tgt, &c, 0, 0, 0, ior); -} - - -#if 0 - /* I have info on these drives, but no drive to test */ - - /* PIONEER DRM-600 */ - -#define SCSI_CMD_PIONEER_EJECT 0xc0 - -#define SCSI_CMD_PIONEER_READ_TOC 0xc1 -typedef struct { - unsigned char first_track; - unsigned char last_track; - unsigned char xxx[2]; -} pioneer_toc_hdr_t; -typedef struct { - unsigned char ctrl; - unsigned char address[3]; -} pioneer_toc_info_t; - -#define SCSI_CMD_PIONEER_READ_SUBCH 0xc2 -typedef struct { - BITFIELD_2(unsigned char, - ctrl : 4, - xxx1 : 4); - unsigned char trackno; - unsigned char indexno; - unsigned char relative_address[3]; - unsigned char absolute_address[3]; -} pioneer_subch_data_t; - -#define SCSI_CMD_PIONEER_SEEK_TRK 0xc8 -#define SCSI_CMD_PIONEER_PLAY_AUDIO 0xc9 -#define SCSI_CMD_PIONEER_PAUSE 0xca - -#define SCSI_CMD_PIONEER_AUDIO_STATUS 0xcc -typedef struct { - unsigned char audio_status; - unsigned char xxx[5]; -} pioneer_status_t; - -/* - * Reserved bits in byte1 - */ -#define PIONEER_LR_END_ADDR 0x10 -#define PIONEER_LR_PAUSE 0x10 -#define PIONEER_LR_RESUME 0x00 - -/* - * Vendor specific bits in the control byte. - */ -#define PIONEER_CTRL_TH 0x00 /* TOC header */ -#define PIONEER_CTRL_TE 0x80 /* one TOC entry */ -#define PIONEER_CTRL_LO 0x40 /* lead-out track info */ - -#define PIONEER_CTRL_A_MSF 0x40 /* min/sec/frame addr */ - -private scsi_ret_t -pioneer_eject( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_PIONEER_EJECT; - - return cdrom_vendor_specific(tgt, &c, 0, 0, 0, ior); -} - -private scsi_ret_t -pioneer_position( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - scsi_ret_t rc; - char *buf = tgt->dev_info.cdrom.result; - pioneer_subch_data_t *st; - - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_PIONEER_READ_SUBCH; - c.scsi_cmd_xfer_len_2 = sizeof(pioneer_subch_data_t); /* 9 bytes */ - - rc = cdrom_vendor_specific(tgt, &c, 0, 0, sizeof(pioneer_subch_data_t), ior); - if (rc != SCSI_RET_SUCCESS) return rc; - - st = (pioneer_subch_data_t *) tgt->cmd_ptr; - - /* XXX can it do ABS addressing e.g. 'logical' ? */ - - sprintf(buf, "MSF Position %d %d %d %d %d %d", - (integer_t)bcd_to_decimal(st->absolute_address[0]), /* min */ - (integer_t)bcd_to_decimal(st->absolute_address[1]), /* sec */ - (integer_t)bcd_to_decimal(st->absolute_address[2]), /* frm */ - (integer_t)bcd_to_decimal(st->relative_address[0]), /* min */ - (integer_t)bcd_to_decimal(st->relative_address[1]), /* sec */ - (integer_t)bcd_to_decimal(st->relative_address[2])); /* frm */ - - tgt->dev_info.cdrom.result_available = TRUE; - return SCSI_RET_SUCCESS; -} - -private scsi_ret_t -pioneer_toc( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - pioneer_toc_hdr_t *th; - pioneer_toc_info_t *t; - char *buf = tgt->dev_info.cdrom.result; - scsi_ret_t rc; - int first, last, i; - - /* Read header first */ - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_PIONEER_READ_TOC; - c.scsi_cmd_xfer_len_2 = sizeof(pioneer_toc_hdr_t); - c.scsi_cmd_ctrl_byte = PIONEER_CTRL_TH; - - rc = cdrom_vendor_specific(tgt, &c, 0, 0, sizeof(pioneer_toc_hdr_t), ior); - if (rc != SCSI_RET_SUCCESS) return rc; - - th = (pioneer_toc_hdr_t *)tgt->cmd_ptr; - first = bcd_to_decimal(th->first_track); - last = bcd_to_decimal(th->last_track); - - /* - * "Get TH" wants summary, "TOC MSF|ABS from_track" wants all - */ - if (cmd[0] == 'G') { - sprintf(buf, "toc header: %d %d %d", 0, first, last); - goto out; - } - - /* - * Must do it one track at a time - */ - sscanf(&cmd[8], "%d", &i); - sprintf(buf, "TOC from track %d:\n", i); - - for ( ; i <= last; i++) { - zero_ior(ior); - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_PIONEER_READ_TOC; - c.scsi_cmd_lba4 = decimal_to_bcd(i); - c.scsi_cmd_xfer_len_2 = sizeof(pioneer_toc_info_t); - c.scsi_cmd_ctrl_byte = PIONEER_CTRL_TE; - - rc = cdrom_vendor_specific(tgt, &c, 0, 0, sizeof(pioneer_toc_info_t), ior); - if (rc != SCSI_RET_SUCCESS) break; - - t = (pioneer_toc_info_t *)tgt->cmd_ptr; - - buf += strlen(buf); - if (cmd[4] == 'M') - sprintf(buf, "%d %d %d %d %d %d\n", - t->ctrl, 0, i, - bcd_to_decimal(t->address[0]), - bcd_to_decimal(t->address[1]), - bcd_to_decimal(t->address[2])); - else -/* THIS IS WRONG */ - sprintf(buf, "%d %d %d %d\n", - t->ctrl, 0, i, - bcd_to_decimal(t->address[0]) * 10000 + - bcd_to_decimal(t->address[1]) * 100 + - bcd_to_decimal(t->address[2])); - } - /* To know how long the last track is */ - zero_ior(ior); - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_PIONEER_READ_TOC; - c.scsi_cmd_xfer_len_2 = sizeof(pioneer_toc_info_t); - c.scsi_cmd_ctrl_byte = PIONEER_CTRL_LO; - - rc = cdrom_vendor_specific(tgt, &c, 0, 0, sizeof(pioneer_toc_info_t), ior); - if (rc != SCSI_RET_SUCCESS) return rc; - - buf += strlen(buf); - t = (pioneer_toc_info_t *)tgt->cmd_ptr; - if (cmd[4] == 'M') - sprintf(buf, "%d %d %d %d %d %d\n", - t->ctrl, 0, 0xaa /* User expects this */, - bcd_to_decimal(t->address[0]), - bcd_to_decimal(t->address[1]), - bcd_to_decimal(t->address[2])); - else -/* THIS IS WRONG */ - sprintf(buf, "%d %d %d %d\n", - t->ctrl, 0, 0xaa /* User expects this */, - bcd_to_decimal(t->address[0]) * 10000 + - bcd_to_decimal(t->address[1]) * 100 + - bcd_to_decimal(t->address[2])); - -out: - tgt->dev_info.cdrom.result_available = TRUE; - return SCSI_RET_SUCCESS; -} - -private scsi_ret_t -pioneer_status( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - pioneer_status_t *st; - char *buf = tgt->dev_info.cdrom.result; - scsi_ret_t rc; - - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_PIONEER_AUDIO_STATUS; - c.scsi_cmd_xfer_len_2 = sizeof(pioneer_status_t); /* 6 bytes */ - - rc = cdrom_vendor_specific(tgt, &c, 0, 0, sizeof(pioneer_status_t), ior); - if (rc != SCSI_RET_SUCCESS) return rc; - - st = (pioneer_status_t*) tgt->cmd_ptr; - decode_status_1( buf, st->audio_status); - - tgt->dev_info.cdrom.result_available = TRUE; - return SCSI_RET_SUCCESS; -} - -private scsi_ret_t -pioneer_play( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - int sm, ss, sf, em, es, ef; - int st, si, et, ei; - scsi_ret_t rc; - - /* - * Seek to desired position - */ - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_PIONEER_SEEK_TRK; - /* - * Play_msf or Play_ti - */ - if (cmd[5] == 'A') { - /* "Play A startM startS startF endM endS endF" */ - - sscanf(&cmd[7], "%d %d %d %d %d %d", - &sm, &ss, &sf, &em, &es, &ef); - - c.scsi_cmd_lba2 = decimal_to_bcd(sm); - c.scsi_cmd_lba3 = decimal_to_bcd(ss); - c.scsi_cmd_lba4 = decimal_to_bcd(sf); - c.scsi_cmd_ctrl_byte = PIONEER_CTRL_A_MSF; - - } else { - /* "Play TI startT startI endT endI" */ - - sscanf(&cmd[8], "%d %d %d %d", &st, &si, &et, &ei); - - c.scsi_cmd_lba3 = decimal_to_bcd(st); - c.scsi_cmd_lba4 = decimal_to_bcd(si); - c.scsi_cmd_ctrl_byte = 0x80; /* Pure speculation!! */ - - } - - rc = cdrom_vendor_specific(tgt, &c, 0, 0, 0, ior); - if (rc != SCSI_RET_SUCCESS) return rc; - - /* - * Now ask it to play until.. - */ - zero_ior( ior ); - - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_PIONEER_PLAY_AUDIO; - c.scsi_cmd_lun_and_relbit = PIONEER_LR_END_ADDR; - - if (cmd[5] == 'A') { - c.scsi_cmd_lba2 = decimal_to_bcd(em); - c.scsi_cmd_lba3 = decimal_to_bcd(es); - c.scsi_cmd_lba4 = decimal_to_bcd(ef); - c.scsi_cmd_ctrl_byte = PIONEER_CTRL_A_MSF; - } else { - c.scsi_cmd_lba3 = decimal_to_bcd(et); - c.scsi_cmd_lba4 = decimal_to_bcd(ei); - c.scsi_cmd_ctrl_byte = 0x80; /* Pure speculation! */ - } - - return cdrom_vendor_specific(tgt, &c, 0, 0, 0, ior); -} - -private scsi_ret_t -pioneer_pause_resume( - target_info_t *tgt, - char *cmd, - io_req_t ior) -{ - scsi_command_group_2 c; - - bzero(&c, sizeof(c)); - c.scsi_cmd_code = SCSI_CMD_PIONEER_PAUSE; - /* - * "Resume" or "Stop" - */ - if (cmd[0] == 'S') - c.scsi_cmd_lun_and_relbit = PIONEER_LR_PAUSE; - else - c.scsi_cmd_lun_and_relbit = PIONEER_LR_RESUME; - - return cdrom_vendor_specific(tgt, &c, 0, 0, 0, ior); -} - - /* DENON DRD-253 */ - -#define SCSI_CMD_DENON_PLAY_AUDIO 0x22 -#define SCSI_CMD_DENON_EJECT 0xe6 -#define SCSI_CMD_DENON_PAUSE_AUDIO 0xe7 -#define SCSI_CMD_DENON_READ_TOC 0xe9 -#define SCSI_CMD_DENON_READ_SUBCH 0xeb - - - /* HITACHI 1750 */ - -#define SCSI_CMD_HITACHI_PLAY_AUDIO_MSF 0xe0 -#define SCSI_CMD_HITACHI_PAUSE_AUDIO 0xe1 -#define SCSI_CMD_HITACHI_EJECT 0xe4 -#define SCSI_CMD_HITACHI_READ_SUBCH 0xe5 -#define SCSI_CMD_HITACHI_READ_TOC 0xe8 - -#endif - -/* - * Tabulate all of the above - */ -private red_list_t cdrom_exceptions[] = { - -#if 0 - For documentation purposes, here are some SCSI-2 compliant drives: - - Vendor Product Rev Comments - - "SONY " "CD-ROMCDU-541 " "2.6a" The NeXT drive -#endif - - /* vendor, product, rev */ - /* can_play_audio */ - /* eject */ - /* current_position */ - /* read_toc */ - /* get_status */ - /* play_msf */ - /* play_ti */ - /* pause_resume */ - /* volume_control */ - - /* We have seen a "RRD42(C)DEC " "4.5d" */ - { "DEC ", "RRD42", "", - 0, 0, 0, 0, 0, 0, 0, 0, rrd42_set_volume }, - - /* We have seen a "CD-ROM DRIVE:84 " "1.0 " */ - { "NEC ", "CD-ROM DRIVE:84", "", - op_not_supported, nec_eject, nec_subchannel, nec_read_toc, - nec_subchannel, nec_play, nec_play, nec_pause_resume, - op_not_supported }, - - /* We have seen a "CD-ROM DRIVE:XM " "3232" */ - { "TOSHIBA ", "CD-ROM DRIVE:XM", "32", - op_not_supported, toshiba_eject, toshiba_subchannel, toshiba_read_toc, - toshiba_subchannel, toshiba_play, toshiba_play, toshiba_pause_resume, - op_not_supported }, - - { "TOSHIBA ", "CD-ROM DRIVE:XM", "33", - op_not_supported, toshiba_eject, toshiba_subchannel, toshiba_read_toc, - toshiba_subchannel, toshiba_play, toshiba_play, toshiba_pause_resume, - op_not_supported }, - -#if 0 - { "PIONEER ", "???????DRM-6", "", - op_not_supported, pioneer_eject, pioneer_position, pioneer_toc, - pioneer_status, pioneer_play, pioneer_play, pioneer_pause_resume, - op_not_supported }, - - { "DENON ", "DRD 25X", "", ...}, - { "HITACHI ", "CDR 1750S", "", ...}, - { "HITACHI ", "CDR 1650S", "", ...}, - { "HITACHI ", "CDR 3650", "", ...}, - -#endif - - /* Zero terminate this list */ - { 0, } -}; - -private void -check_red_list( - target_info_t *tgt, - scsi2_inquiry_data_t *inq) - -{ - red_list_t *list; - - for (list = &cdrom_exceptions[0]; list->vendor; list++) { - - /* - * Prefix-Match all strings - */ - if ((strncmp(list->vendor, (const char *)inq->vendor_id, - strlen(list->vendor)) == 0) && - (strncmp(list->product, (const char *)inq->product_id, - strlen(list->product)) == 0) && - (strncmp(list->rev, (const char *)inq->product_rev, - strlen(list->rev)) == 0)) { - /* - * One of them.. - */ - if (tgt->dev_info.cdrom.violates_standards != list) { - tgt->dev_info.cdrom.violates_standards = list; - curse_the_vendor( list, TRUE ); - } - return; - } - } -} -#endif /* NSCSI > 0 */ diff --git a/scsi/rz_cpu.c b/scsi/rz_cpu.c deleted file mode 100644 index 77c0683..0000000 --- a/scsi/rz_cpu.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: rz_cpu.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 7/91 - * - * Top layer of the SCSI driver: interface with the MI. - * This file contains operations specific to CPU-like devices. - * - * We handle here the case of simple devices which do not use any - * sophisticated host-to-host communication protocol, they look - * very much like degenerative cases of TAPE devices. - * - * For documentation and debugging, we also provide code to act like one. - */ - -#include <mach/std_types.h> -#include <scsi/compat_30.h> - -#include <scsi/scsi.h> -#include <scsi/scsi_defs.h> -#include <scsi/rz.h> - -#if (NSCSI > 0) - -void sccpu_act_as_target(); /* forwards */ -void sccpu_start(); - -/* - * This function decides which 'protocol' we well speak - * to a cpu target. For now the decision is left to a - * global var. XXXXXXX - */ -extern scsi_devsw_t scsi_host; -scsi_devsw_t *scsi_cpu_protocol = /* later &scsi_host*/ - &scsi_devsw[SCSI_CPU]; - -void sccpu_new_initiator(self, initiator) - target_info_t *self, *initiator; -{ - initiator->dev_ops = scsi_cpu_protocol; - if (initiator == self) { - self->flags = TGT_DID_SYNCH|TGT_FULLY_PROBED|TGT_ONLINE| - TGT_ALIVE|TGT_US; - self->dev_info.cpu.req_pending = FALSE; - } else { - initiator->flags = TGT_ONLINE|TGT_ALIVE; - initiator->dev_info.cpu.req_pending = TRUE; - } -} - -void sccpu_strategy(ior) - register io_req_t ior; -{ - void sccpu_start(); - - rz_simpleq_strategy(ior, sccpu_start); -} - -void sccpu_start(tgt, done) - target_info_t *tgt; - boolean_t done; -{ - io_req_t head, ior; - scsi_ret_t ret; - - /* this is to the doc & debug code mentioned in the beginning */ - if (!done && tgt->dev_info.cpu.req_pending) { - panic("sccpu_act_as_target called"); -#if 0 - sccpu_act_as_target( tgt); -#endif - return; - } - - ior = tgt->ior; - if (ior == 0) - return; - - if (done) { - - /* see if we must retry */ - if ((tgt->done == SCSI_RET_RETRY) && - ((ior->io_op & IO_INTERNAL) == 0)) { - delay(1000000);/*XXX*/ - goto start; - } else - /* got a bus reset ? shouldn't matter */ - if ((tgt->done == (SCSI_RET_ABORTED|SCSI_RET_RETRY)) && - ((ior->io_op & IO_INTERNAL) == 0)) { - goto start; - } else - - /* check completion status */ - - if (tgt->cur_cmd == SCSI_CMD_REQUEST_SENSE) { - scsi_sense_data_t *sns; - - ior->io_op = ior->io_temporary; - ior->io_error = D_IO_ERROR; - ior->io_op |= IO_ERROR; - - sns = (scsi_sense_data_t *)tgt->cmd_ptr; - if (scsi_debug) - scsi_print_sense_data(sns); - - if (scsi_check_sense_data(tgt, sns)) { - if (sns->u.xtended.ili) { - if (ior->io_op & IO_READ) { - int residue; - - residue = sns->u.xtended.info0 << 24 | - sns->u.xtended.info1 << 16 | - sns->u.xtended.info2 << 8 | - sns->u.xtended.info3; - if (scsi_debug) - printf("Cpu Short Read (%d)\n", residue); - /* - * NOTE: residue == requested - actual - * We only care if > 0 - */ - if (residue < 0) residue = 0;/* sanity */ - ior->io_residual += residue; - ior->io_error = 0; - ior->io_op &= ~IO_ERROR; - /* goto ok */ - } - } - } - } - - else if (tgt->done != SCSI_RET_SUCCESS) { - - if (tgt->done == SCSI_RET_NEED_SENSE) { - - ior->io_temporary = ior->io_op; - ior->io_op = IO_INTERNAL; - if (scsi_debug) - printf("[NeedSns x%x x%x]", ior->io_residual, ior->io_count); - scsi_request_sense(tgt, ior, 0); - return; - - } else if (tgt->done == SCSI_RET_RETRY) { - /* only retry here READs and WRITEs */ - if ((ior->io_op & IO_INTERNAL) == 0) { - ior->io_residual = 0; - goto start; - } else{ - ior->io_error = D_WOULD_BLOCK; - ior->io_op |= IO_ERROR; - } - } else { - ior->io_error = D_IO_ERROR; - ior->io_op |= IO_ERROR; - } - } - - if (scsi_debug) - printf("[Resid x%x]", ior->io_residual); - - /* dequeue next one */ - head = ior; - - simple_lock(&tgt->target_lock); - ior = head->io_next; - tgt->ior = ior; - if (ior) - ior->io_prev = head->io_prev; - simple_unlock(&tgt->target_lock); - - iodone(head); - - if (ior == 0) - return; - } - ior->io_residual = 0; -start: - if (ior->io_op & IO_READ) { - ret = scsi_receive( tgt, ior ); - } else if ((ior->io_op & IO_INTERNAL) == 0) { - ret = scsi_send( tgt, ior ); - } -} - - -#if 0 -/* XX turned off this code because it's impossible - to reference 'end' and other such magic symbols - from boot modules. */ -/* - * This is a simple code to make us act as a dumb - * processor type. Use for debugging only. - */ -static struct io_req sccpu_ior; -vm_offset_t sccpu_buffer; /* set this with debugger */ - -void sccpu_act_as_target(self) - target_info_t *self; -{ - static char inq_data[] = "\3\0\1\0\040\0\0\0Mach3.0 Processor Link v0.1"; - static char sns_data[] = "\160\0\0\0\0\0\0\0\0"; - - self->dev_info.cpu.req_pending = FALSE; - sccpu_ior.io_next = 0; -#define MAXSIZE 1024*64 - sccpu_ior.io_count = (MAXSIZE < self->dev_info.cpu.req_len) ? - MAXSIZE : self->dev_info.cpu.req_len; - - switch (self->dev_info.cpu.req_cmd) { - case SCSI_CMD_INQUIRY: - sccpu_ior.io_data = inq_data; break; - case SCSI_CMD_REQUEST_SENSE: - sccpu_ior.io_data = sns_data; break; - default: - if (sccpu_buffer == 0) { - /* ( read my lips :-) */ - /* extern char end[]; */ - sccpu_buffer = trunc_page(kalloc(MAXSIZE)); - } - sccpu_ior.io_data = (char*)sccpu_buffer; break; - } - - if (self->dev_info.cpu.req_cmd == SCSI_CMD_SEND) { - self->cur_cmd = SCSI_CMD_READ; - sccpu_ior.io_op = IO_READ; - } else { - self->cur_cmd = SCSI_CMD_WRITE; - sccpu_ior.io_op = IO_WRITE; - } - self->ior = &sccpu_ior; -} -#endif - -/*#define PERF*/ -#ifdef PERF -int test_read_size = 512; -int test_read_nreads = 1000; -int test_read_bdev = 0; -int test_read_or_write = 1; - -#include <sys/time.h> -#include <machine/machspl.h> /* spl */ - -test_read(max) -{ - int i, ssk, usecs; - struct timeval start, stop; - spl_t s; - - if (max != 0) - test_read_nreads = max; - - s = spl0(); - start = time; - if (test_read_or_write) read_test(); else write_test(); - stop = time; - splx(s); - - usecs = stop.tv_usec - start.tv_usec; - if (usecs < 0) { - stop.tv_sec -= 1; - usecs += 1000000; - } - printf("Size %d count %d time %3d sec %d us\n", - test_read_size, test_read_nreads, - stop.tv_sec - start.tv_sec, usecs); -} - -read_test() -{ - struct io_req io, io1; - register int i; - - bzero(&io, sizeof(io)); - io.io_unit = test_read_bdev; - io.io_op = IO_READ; - io.io_count = test_read_size; - io.io_data = (char*)sccpu_buffer; - io1 = io; - - sccpu_strategy(&io); - for (i = 1; i < test_read_nreads; i += 2) { - io1.io_op = IO_READ; - sccpu_strategy(&io1); - iowait(&io); - io.io_op = IO_READ; - sccpu_strategy(&io); - iowait(&io1); - } - iowait(&io); -} - -write_test() -{ - struct io_req io, io1; - register int i; - - bzero(&io, sizeof(io)); - io.io_unit = test_read_bdev; - io.io_op = IO_WRITE; - io.io_count = test_read_size; - io.io_data = (char*)sccpu_buffer; - io1 = io; - - sccpu_strategy(&io); - for (i = 1; i < test_read_nreads; i += 2) { - io1.io_op = IO_WRITE; - sccpu_strategy(&io1); - iowait(&io); - io.io_op = IO_WRITE; - sccpu_strategy(&io); - iowait(&io1); - } - iowait(&io); -} - -tur_test() -{ - struct io_req io; - register int i; - char *a; - struct timeval start, stop; - spl_t s; - target_info_t *tgt; - - bzero(&io, sizeof(io)); - io.io_unit = test_read_bdev; - io.io_data = (char*)&io;/*unused but kernel space*/ - - rz_check(io.io_unit, &a, &tgt); - s = spl0(); - start = time; - for (i = 0; i < test_read_nreads; i++) { - io.io_op = IO_INTERNAL; - scsi_test_unit_ready(tgt,&io); - } - stop = time; - splx(s); - i = stop.tv_usec - start.tv_usec; - if (i < 0) { - stop.tv_sec -= 1; - i += 1000000; - } - printf("%d test-unit-ready took %3d sec %d us\n", - test_read_nreads, - stop.tv_sec - start.tv_sec, i); -} - -/*#define MEM_PERF*/ -#ifdef MEM_PERF -int mem_read_size = 1024; /* ints! */ -int mem_read_nreads = 1000; -volatile int *mem_read_address = (volatile int*)0xb0080000; -volatile int *mem_write_address = (volatile int*)0xb0081000; - -mem_test(max, which) -{ - int i, ssk, usecs; - struct timeval start, stop; - int (*fun)(), mwrite_test(), mread_test(), mcopy_test(); - spl_t s; - - if (max == 0) - max = mem_read_nreads; - - switch (which) { - case 1: fun = mwrite_test; break; - case 2: fun = mcopy_test; break; - default:fun = mread_test; break; - } - - s = spl0(); - start = time; - for (i = 0; i < max; i++) - (*fun)(mem_read_size); - stop = time; - splx(s); - - usecs = stop.tv_usec - start.tv_usec; - if (usecs < 0) { - stop.tv_sec -= 1; - usecs += 1000000; - } - printf("Size %d count %d time %3d sec %d us\n", - mem_read_size*4, max, - stop.tv_sec - start.tv_sec, usecs); -} - -mread_test(max) - register int max; -{ - register int i; - register volatile int *addr = mem_read_address; - - for (i = 0; i < max; i++) { - register int j = *addr++; - } -} -mwrite_test(max) - register int max; -{ - register int i; - register volatile int *addr = mem_read_address; - - for (i = 0; i < max; i++) { - *addr++ = i; - } -} - -mcopy_test(max) - register int max; -{ - register volatile int *from = mem_read_address; - register volatile int *to = mem_write_address; - register volatile int *endaddr; - - endaddr = to + max; - while (to < endaddr) - *to++ = *from++; - -} -#endif /*MEM_PERF*/ - -#endif /*PERF*/ - -#endif /* NSCSI > 0 */ diff --git a/scsi/rz_disk.c b/scsi/rz_disk.c deleted file mode 100644 index 87a992b..0000000 --- a/scsi/rz_disk.c +++ /dev/null @@ -1,1222 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: rz_disk.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Top layer of the SCSI driver: interface with the MI. - * This file contains operations specific to disk-like devices. - * - * Modified by Kevin T. Van Maren to use a common partition code - * with the ide driver, and support 'slices'. - */ - - -#include <scsi/scsi.h> -#if (NSCSI > 0) - -#include <device/buf.h> -#include <device/disk_status.h> -#include <device/device_types.h> -#include <device/param.h> -#include <device/errno.h> - -#include <kern/time_out.h> -#include <machine/machspl.h> /* spl definitions */ -#include <mach/std_types.h> -#include <platforms.h> - -#include <scsi/compat_30.h> -#include <scsi/scsi.h> -#include <scsi/scsi_defs.h> -#include <scsi/rz.h> -#include <scsi/rz_labels.h> - -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ -#include <sys/kernel.h> /* for hz */ -#endif /*MACH_KERNEL*/ - -#include <sys/types.h> -#include <sys/ioctl.h> -#include "vm_param.h" -#include <vm/vm_kern.h> -#include <vm/pmap.h> - -extern void scdisk_read(), scdisk_write(), - scsi_long_read(), scsi_long_write(); - -void scdisk_start(); /* forwards */ -void scdisk_start_rw(); -unsigned dkcksum(); - -#if 0 -struct diskpart scsi_array[8*64]; -#endif 0 - - -/* THIS IS THE BOTTOM LAYER FOR THE SCSI PARTITION CODE */ -typedef struct scsi_driver_info { - target_info_t *tgt; - io_req_t ior; - void (*readfun)(); - int sectorsize; -} scsi_driver_info; - -int scsi_read_fun(scsi_driver_info *param, int sectornum, void *buff) -{ - char *psave; - int result = TRUE; /* SUCCESS */ - psave=param->ior->io_data; /* is this necessary ? */ - - param->ior->io_data=buff; - param->ior->io_count = param->sectorsize; - param->ior->io_op = IO_READ; - param->ior->io_error = 0; - param->tgt->ior = param->ior; - - (*param->readfun)( param->tgt, sectornum, param->ior); - iowait(param->ior); - - param->ior->io_data=psave; /* restore the io_data pointer ?? */ - return(result); -} - - - -/* - * Specialized side of the open routine for disks - */ -scsi_ret_t scdisk_open(tgt, req) - target_info_t *tgt; - io_req_t req; -{ - register int i, dev_bsize; - scsi_ret_t ret = /* SCSI_RET_SUCCESS; */ -1; - unsigned int disk_size, secs_per_cyl, sector_size; - scsi_rcap_data_t *cap; - struct disklabel *label; - io_req_t ior; - void (*readfun)() = scdisk_read; - char *data = (char *)0; - - int numpart; - - scsi_driver_info scsi_info; - char drive_name[10]; /* used for disklabel strings */ - - if (tgt->flags & TGT_ONLINE) - return SCSI_RET_SUCCESS; - - /* - * Dummy ior for proper sync purposes - */ - io_req_alloc(ior,0); - ior->io_next = 0; - ior->io_count = 0; - - /* - * Set the LBN to DEV_BSIZE with a MODE SELECT. - * If this fails we try a couple other tricks. - */ - dev_bsize = 0; - for (i = 0; i < 5; i++) { - ior->io_op = IO_INTERNAL; - ior->io_error = 0; - ret = scdisk_mode_select(tgt, DEV_BSIZE, ior, 0, 0, 0); - if (ret == SCSI_RET_SUCCESS) { - dev_bsize = DEV_BSIZE; - break; - } - if (ret == SCSI_RET_RETRY) { - timeout(wakeup, tgt, 2*hz); - await(tgt); - } - if (ret == SCSI_RET_DEVICE_DOWN) - goto done; - } -#if 0 - if (ret != SCSI_RET_SUCCESS) { - scsi_error( tgt, SCSI_ERR_MSEL, ret, 0); - ret = D_INVALID_SIZE; - goto done; - } -#endif - /* - * Do a READ CAPACITY to get max size. Check LBN too. - */ - for (i = 0; i < 5; i++) { - ior->io_op = IO_INTERNAL; - ior->io_error = 0; - ret = scsi_read_capacity(tgt, 0, ior); - if (ret == SCSI_RET_SUCCESS) - break; - } - if (ret == SCSI_RET_SUCCESS) { - int val; - - cap = (scsi_rcap_data_t*) tgt->cmd_ptr; - disk_size = (cap->lba1<<24) | - (cap->lba2<<16) | - (cap->lba3<< 8) | - cap->lba4; - if (scsi_debug) - printf("rz%d holds %d blocks\n", tgt->unit_no, disk_size); - val = (cap->blen1<<24) | - (cap->blen2<<16) | - (cap->blen3<<8 ) | - cap->blen4; - if (dev_bsize == 0) - dev_bsize = val; - else - if (val != dev_bsize) panic("read capacity bad"); - - if (disk_size > SCSI_CMD_READ_MAX_LBA) - tgt->flags |= TGT_BIG; - - } else { - printf("Unknown disk capacity??\n"); - disk_size = -1; - } - /* - * Mandatory long-form commands ? - */ - if (BGET(scsi_use_long_form,(unsigned char)tgt->masterno,tgt->target_id)) - tgt->flags |= TGT_BIG; - if (tgt->flags & TGT_BIG) - readfun = scsi_long_read; - - /* - * Some CDROMS truly dislike 512 as LBN. - * Use a MODE_SENSE to cover for this case. - */ - if (dev_bsize == 0) { - scsi_mode_sense_data_t *m; - - ior->io_op = IO_INTERNAL; - ior->io_error = 0; - ret = scsi_mode_sense(tgt, 0/*pagecode*/, 32/*?*/, ior); - if (ret == SCSI_RET_SUCCESS) { - m = (scsi_mode_sense_data_t *) tgt->cmd_ptr; - dev_bsize = - m->bdesc[0].blen_msb << 16 | - m->bdesc[0].blen << 8 | - m->bdesc[0].blen_lsb; - } - } - - /* - * Find out about the phys disk geometry -- scsi specific - */ - - ior->io_op = IO_INTERNAL; - ior->io_error = 0; - ret = scsi_read_capacity( tgt, 1, ior); - if (ret == SCSI_RET_SUCCESS) { - cap = (scsi_rcap_data_t*) tgt->cmd_ptr; - secs_per_cyl = (cap->lba1<<24) | (cap->lba2<<16) | - (cap->lba3<< 8) | cap->lba4; - secs_per_cyl += 1; - sector_size = (cap->blen1<<24) | (cap->blen2<<16) | - (cap->blen3<<8 ) | cap->blen4; - } else { - sector_size = dev_bsize ? dev_bsize : DEV_BSIZE; - secs_per_cyl = disk_size; - } - if (dev_bsize == 0) - dev_bsize = sector_size; - - if (scsi_debug) - printf("rz%d: %d sect/cyl %d bytes/sec\n", tgt->unit_no, - secs_per_cyl, sector_size); - - /* - * At this point, one way or other, we are committed to - * a given disk capacity and sector size. - */ - tgt->block_size = dev_bsize; - - /* - * Get partition table off pack - */ - -#ifdef MACH_KERNEL - ior->io_data = (char *)kalloc(sector_size); -#endif /*MACH_KERNEL*/ - - scsi_info.tgt=tgt; - scsi_info.ior=ior; - scsi_info.readfun=readfun; - scsi_info.sectorsize=sector_size; - - /* label has NOT been allocated space yet! set to the tgt disklabel */ - label=&scsi_info.tgt->dev_info.disk.l; - - sprintf(drive_name, "sd%d:", tgt->unit_no); - - if (scsi_debug) - printf("Using bogus geometry: 32 sectors/track, 64 heads\n"); - - fudge_bsd_label(label, DTYPE_SCSI, disk_size /* /(32*64)*/ , - 64, 32, sector_size, 8); - - numpart=get_only_partition(&scsi_info, (*scsi_read_fun), - tgt->dev_info.disk.scsi_array, MAX_SCSI_PARTS, disk_size, drive_name); - - printf("%s %d partitions found\n",drive_name,numpart); - - ret=SCSI_RET_SUCCESS; /* if 0, return SCSI_RET_SUCCESS */ - - -done: - io_req_free(ior); - - return(ret); -} - - -/* - * Disk strategy routine - */ -int scdisk_strategy(ior) - register io_req_t ior; -{ - target_info_t *tgt; - register scsi_softc_t *sc; - register int i = ior->io_unit, part; - register unsigned rec, max; - spl_t s; - struct diskpart *label; - - sc = scsi_softc[rzcontroller(i)]; - tgt = sc->target[rzslave(i)]; - part = rzpartition(i); - - /* - * Validate request - */ - - /* readonly ? */ - if ((tgt->flags & TGT_READONLY) && - (ior->io_op & (IO_READ|IO_INTERNAL) == 0)) { - ior->io_error = D_READ_ONLY; - ior->io_op |= IO_ERROR; - ior->io_residual = ior->io_count; - iodone(ior); - return ior->io_error; - } - - rec = ior->io_recnum; - - label=lookup_part(tgt->dev_info.disk.scsi_array, part); - if (!label) { - if (scsi_debug) - printf("sc strategy -- bad partition\n"); - ior->io_error = D_INVALID_SIZE; - ior->io_op |= IO_ERROR; - ior->io_residual = ior->io_count; - iodone(ior); - return ior->io_error; - } - else max=label->size; - if (max == -1) /* what about 0? */ - max = tgt->dev_info.disk.l.d_secperunit - - - label->start; - - i = (ior->io_count + tgt->block_size - 1) / tgt->block_size; - if (((rec + i) > max) || (ior->io_count < 0) || -#if later - ((rec <= LABELSECTOR) && ((tgt->flags & TGT_WRITE_LABEL) == 0)) -#else - FALSE -#endif - ) { - ior->io_error = D_INVALID_SIZE; - ior->io_op |= IO_ERROR; - ior->io_residual = ior->io_count; - iodone(ior); - return ior->io_error; - } - /* - * Find location on disk: secno and cyl (for disksort) - */ - rec += label->start; - ior->io_residual = rec / tgt->dev_info.disk.l.d_secpercyl; - - /* - * Enqueue operation - */ - s = splbio(); - simple_lock(&tgt->target_lock); - if (tgt->ior) { - disksort(tgt->ior, ior); - simple_unlock(&tgt->target_lock); - splx(s); - } else { - ior->io_next = 0; - tgt->ior = ior; - simple_unlock(&tgt->target_lock); - splx(s); - - scdisk_start(tgt,FALSE); - } - - return D_SUCCESS; -} - -/*#define CHECKSUM*/ -#ifdef CHECKSUM -int max_checksum_size = 0x2000; -#endif CHECKSUM - -/* - * Start/completion routine for disks - */ -void scdisk_start(tgt, done) - target_info_t *tgt; - boolean_t done; -{ - register io_req_t ior = tgt->ior; - register unsigned part; -#ifdef CHECKSUM - register unsigned secno; -#endif - struct diskpart *label; - - if (ior == 0) - return; - - if (tgt->flags & TGT_BBR_ACTIVE) - { - scdisk_bbr_start(tgt, done); - return; - } - - if (done) { - register unsigned int xferred; - unsigned int max_dma_data; - - max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - /* see if we must retry */ - if ((tgt->done == SCSI_RET_RETRY) && - ((ior->io_op & IO_INTERNAL) == 0)) { - delay(1000000);/*XXX*/ - goto start; - } else - /* got a bus reset ? pifff.. */ - if ((tgt->done == (SCSI_RET_ABORTED|SCSI_RET_RETRY)) && - ((ior->io_op & IO_INTERNAL) == 0)) { - if (xferred = ior->io_residual) { - ior->io_data -= xferred; - ior->io_count += xferred; - ior->io_recnum -= xferred / tgt->block_size; - ior->io_residual = 0; - } - goto start; - } else - /* - * Quickly check for errors: if anything goes wrong - * we do a request sense, see if that is what we did. - */ - if (tgt->cur_cmd == SCSI_CMD_REQUEST_SENSE) { - scsi_sense_data_t *sns; - unsigned int blockno; - char *outcome; - - ior->io_op = ior->io_temporary; - - sns = (scsi_sense_data_t *)tgt->cmd_ptr; - if (sns->addr_valid) - blockno = sns->u.xtended.info0 << 24 | - sns->u.xtended.info1 << 16 | - sns->u.xtended.info2 << 8 | - sns->u.xtended.info3; - else { - part = rzpartition(ior->io_unit); - label = lookup_part(tgt->dev_info.disk.scsi_array, part); - blockno = label->start; - blockno += ior->io_recnum; - if (!label) blockno=-1; - } - - if (scsi_check_sense_data(tgt, sns)) { - ior->io_error = 0; - if ((tgt->done == SCSI_RET_RETRY) && - ((ior->io_op & IO_INTERNAL) == 0)) { - delay(1000000);/*XXX*/ - goto start; - } - outcome = "Recovered"; - } else { - outcome = "Unrecoverable"; - ior->io_error = D_IO_ERROR; - ior->io_op |= IO_ERROR; - } - if ((tgt->flags & TGT_OPTIONAL_CMD) == 0) { - printf("%s Error, rz%d: %s%s%d\n", outcome, - tgt->target_id + (tgt->masterno * 8), - (ior->io_op & IO_READ) ? "Read" : - ((ior->io_op & IO_INTERNAL) ? "(command)" : "Write"), - " disk error, phys block no. ", blockno); - - scsi_print_sense_data(sns); - - /* - * On fatal read/write errors try replacing the bad block - * The bbr routine will return TRUE iff it took control - * over the target for all subsequent operations. In this - * event, the queue of requests is effectively frozen. - */ - if (ior->io_error && - ((sns->error_class == SCSI_SNS_XTENDED_SENSE_DATA) && - ((sns->u.xtended.sense_key == SCSI_SNS_HW_ERR) || - (sns->u.xtended.sense_key == SCSI_SNS_MEDIUM_ERR))) && - scdisk_bad_block_repl(tgt, blockno)) - return; - } - } - - /* - * See if we had errors - */ - else if (tgt->done != SCSI_RET_SUCCESS) { - - if (tgt->done == SCSI_RET_NEED_SENSE) { - - ior->io_temporary = ior->io_op; - ior->io_op = IO_INTERNAL; - scsi_request_sense(tgt, ior, 0); - return; - - } else if (tgt->done == SCSI_RET_DEVICE_DOWN) { - ior->io_error = D_DEVICE_DOWN; - ior->io_op |= IO_ERROR; - } else { - printf("%s%x\n", "?rz_disk Disk error, ret=x", tgt->done); - ior->io_error = D_IO_ERROR; - ior->io_op |= IO_ERROR; - } - } - /* - * No errors. - * See if we requested more than the max - * (We use io_residual in a flip-side way here) - */ - else if (ior->io_count > (xferred = max_dma_data)) { - ior->io_residual += xferred; - ior->io_count -= xferred; - ior->io_data += xferred; - ior->io_recnum += xferred / tgt->block_size; - goto start; - } - else if (xferred = ior->io_residual) { - ior->io_data -= xferred; - ior->io_count += xferred; - ior->io_recnum -= xferred / tgt->block_size; - ior->io_residual = 0; - } /* that's it */ - -#ifdef CHECKSUM - if ((ior->io_op & IO_READ) && (ior->io_count < max_checksum_size)) { - part = rzpartition(ior->io_unit); - label=lookup_part(tgt->dev_info.disk.scsi_array, part); - if (!label) printf("NOT FOUND!\n"); - secno = ior->io_recnum + label->start; - scdisk_bcheck(secno, ior->io_data, ior->io_count); - } -#endif CHECKSUM - - /* dequeue next one */ - { - io_req_t next; - - simple_lock(&tgt->target_lock); - next = ior->io_next; - tgt->ior = next; - simple_unlock(&tgt->target_lock); - - iodone(ior); - if (next == 0) - return; - - ior = next; - } - -#ifdef CHECKSUM - if (((ior->io_op & IO_READ) == 0) && (ior->io_count < max_checksum_size)) { - part = rzpartition(ior->io_unit); - label=lookup_part(tgt->dev_info.disk.scsi_array, part); - secno = ior->io_recnum + label->start; - scdisk_checksum(secno, ior->io_data, ior->io_count); - } -#endif CHECKSUM - } - ior->io_residual = 0; -start: - scdisk_start_rw( tgt, ior); -} - -void scdisk_start_rw( tgt, ior) - target_info_t *tgt; - register io_req_t ior; -{ - unsigned int part, secno; - register boolean_t long_form; - struct diskpart *label; - - part = rzpartition(ior->io_unit); - label=lookup_part(tgt->dev_info.disk.scsi_array, part); - if (!label) - printf("NOT FOUND!\n"); - secno = ior->io_recnum + label->start; - - /* Use long form if either big block addresses or - the size is more than we can fit in one byte */ - long_form = (tgt->flags & TGT_BIG) || - (ior->io_count > (256 * tgt->block_size)); - if (ior->io_op & IO_READ) - (long_form ? scsi_long_read : scdisk_read)(tgt, secno, ior); - else if ((ior->io_op & IO_INTERNAL) == 0) - (long_form ? scsi_long_write : scdisk_write)(tgt, secno, ior); -} - -#include <sys/ioctl.h> -#ifdef ULTRIX_COMPAT -#include <mips/PMAX/rzdisk.h> -#endif /*ULTRIX_COMPAT*/ - -io_return_t -scdisk_get_status(dev, tgt, flavor, status, status_count) - int dev; - target_info_t *tgt; - dev_flavor_t flavor; - dev_status_t status; - natural_t *status_count; -{ - struct disklabel *lp; - struct diskpart *label; - - lp = &tgt->dev_info.disk.l; - - switch (flavor) { -#ifdef MACH_KERNEL - case DEV_GET_SIZE: - - label=lookup_part(tgt->dev_info.disk.scsi_array, rzpartition(dev)); - status[DEV_GET_SIZE_DEVICE_SIZE] = label->size * lp->d_secsize; - status[DEV_GET_SIZE_RECORD_SIZE] = tgt->block_size; - *status_count = DEV_GET_SIZE_COUNT; - break; -#endif - - case DIOCGDINFO: - *(struct disklabel *)status = *lp; -#ifdef MACH_KERNEL - *status_count = sizeof(struct disklabel)/sizeof(int); -#endif MACH_KERNEL - break; - - case DIOCGDINFO - (0x10<<16): - *(struct disklabel *)status = *lp; -#ifdef MACH_KERNEL - *status_count = sizeof(struct disklabel)/sizeof(int) - 4; -#endif MACH_KERNEL - break; - -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ -#if ULTRIX_COMPAT - case SCSI_MODE_SENSE: /*_IOWR(p, 9, struct mode_sel_sns_params) */ - break; - case DIOCGETPT: /*_IOR(p, 1, struct pt) */ - case SCSI_GET_SENSE: /*_IOR(p, 10, struct extended_sense) */ - return ul_disk_ioctl(tgt, flavor, status, status_count); -#endif /*ULTRIX_COMPAT*/ -#endif /*!MACH_KERNEL*/ - -#if 0 - case DIOCRFORMAT: - break; -#endif - default: -#ifdef i386 - return(scsi_i386_get_status(dev, tgt, flavor, status, status_count)); -#else i386 - return(D_INVALID_OPERATION); -#endif i386 - } - return D_SUCCESS; -} - -io_return_t -scdisk_set_status(dev, tgt, flavor, status, status_count) - int dev; - target_info_t *tgt; - dev_flavor_t flavor; - dev_status_t status; - natural_t status_count; -{ - io_return_t error = D_SUCCESS; - struct disklabel *lp; - - lp = &tgt->dev_info.disk.l; - - - switch (flavor) { - case DIOCSRETRIES: -#ifdef MACH_KERNEL - if (status_count != sizeof(int)) - return D_INVALID_SIZE; -#endif /* MACH_KERNEL */ - scsi_bbr_retries = *(int *)status; - break; - - case DIOCWLABEL: - case DIOCWLABEL - (0x10<<16): - if (*(int*)status) - tgt->flags |= TGT_WRITE_LABEL; - else - tgt->flags &= ~TGT_WRITE_LABEL; - break; - case DIOCSDINFO: - case DIOCSDINFO - (0x10<<16): - case DIOCWDINFO: - case DIOCWDINFO - (0x10<<16): -#ifdef MACH_KERNEL - if (status_count != sizeof(struct disklabel) / sizeof(int)) - return D_INVALID_SIZE; -#endif /* MACH_KERNEL */ - error = setdisklabel(lp, (struct disklabel*) status); - if (error || (flavor == DIOCSDINFO) || (flavor == DIOCSDINFO - (0x10<<16))) - return error; - error = scdisk_writelabel(tgt); - break; - -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ -#if ULTRIX_COMPAT - case SCSI_FORMAT_UNIT: /*_IOW(p, 4, struct format_params) */ - case SCSI_REASSIGN_BLOCK: /*_IOW(p, 5, struct reassign_params) */ - case SCSI_READ_DEFECT_DATA: /*_IOW(p, 6, struct read_defect_params) */ - case SCSI_VERIFY_DATA: /*_IOW(p, 7, struct verify_params) */ - case SCSI_MODE_SELECT: /*_IOW(p, 8, struct mode_sel_sns_params) */ - case SCSI_MODE_SENSE: /*_IOW(p, 9, struct mode_sel_sns_params) */ - case SCSI_GET_INQUIRY_DATA: /*_IOW(p, 11, struct inquiry_info) */ - return ul_disk_ioctl(tgt, flavor, status, status_count); -#endif /*ULTRIX_COMPAT*/ -#endif /*!MACH_KERNEL*/ - -#if notyet - case DIOCWFORMAT: - case DIOCSBAD: /* ?? how ? */ -#endif - default: -#ifdef i386 - error = scsi_i386_set_status(dev, tgt, flavor, status, status_count); -#else i386 - error = D_INVALID_OPERATION; -#endif i386 - } - return error; -} - -static int grab_it(tgt, ior) - target_info_t *tgt; - io_req_t ior; -{ - spl_t s; - - s = splbio(); - simple_lock(&tgt->target_lock); - if (!tgt->ior) - tgt->ior = ior; - simple_unlock(&tgt->target_lock); - splx(s); - - if (tgt->ior != ior) - return D_ALREADY_OPEN; - return D_SUCCESS; -} - -/* Write back a label to the disk */ -io_return_t scdisk_writelabel(tgt) - target_info_t *tgt; -{ - -printf("scdisk_writelabel: NO LONGER IMPLEMENTED\n"); -#if 0 -/* Taken out at Bryan's suggestion until 'fixed' for slices */ - - io_req_t ior; - char *data = (char *)0; - struct disklabel *label; - io_return_t error; - int dev_bsize = tgt->block_size; - - io_req_alloc(ior,0); -#ifdef MACH_KERNEL - data = (char *)kalloc(dev_bsize); -#else /*MACH_KERNEL*/ - data = (char *)ior->io_data; -#endif /*MACH_KERNEL*/ - ior->io_next = 0; - ior->io_prev = 0; - ior->io_data = data; - ior->io_count = dev_bsize; - ior->io_op = IO_READ; - ior->io_error = 0; - - if (grab_it(tgt, ior) != D_SUCCESS) { - error = D_ALREADY_OPEN; - goto ret; - } - - scdisk_read( tgt, tgt->dev_info.disk.labelsector, ior); - iowait(ior); - if (error = ior->io_error) - goto ret; - - label = (struct disklabel *) &data[tgt->dev_info.disk.labeloffset]; - *label = tgt->dev_info.disk.l; - - ior->io_next = 0; - ior->io_prev = 0; - ior->io_data = data; - ior->io_count = dev_bsize; - ior->io_op = IO_WRITE; - - while (grab_it(tgt, ior) != D_SUCCESS) ; /* ahem */ - - scdisk_write( tgt, tgt->dev_info.disk.labelsector, ior); - iowait(ior); - - error = ior->io_error; -ret: -#ifdef MACH_KERNEL - if (data) kfree((int)data, dev_bsize); -#endif /*MACH_KERNEL*/ - io_req_free(ior); - return error; - -#endif 0 scdisk_writelabel -return -1; /* FAILURE ? */ -} - -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ -#if ULTRIX_COMPAT - -io_return_t ul_disk_ioctl(tgt, flavor, status, status_count) - target_info_t *tgt; - dev_flavor_t flavor; - dev_status_t status; - natural_t status_count; -{ - io_return_t ret; - scsi_ret_t err = SCSI_RET_ABORTED;/*xxx*/ - io_req_t ior; - - if (!suser()) - return EACCES; - - ior = geteblk(sizeof(struct defect_descriptors)); - ior->io_next = 0; - ior->io_count = 0; - ior->io_op = IO_INTERNAL; - ior->io_error = 0; - ior->io_recnum = 0; - ior->io_residual = 0; - - switch (flavor) { - - case DIOCGETPT: { /*_IOR(p, 1, struct pt) */ - scsi_dec_label_t *p; - struct disklabel *lp; - int i; - - lp = &tgt->dev_info.disk.l; - p = (scsi_dec_label_t *)status; - - p->magic = DEC_PARTITION_MAGIC; - p->in_use = 1; - for (i = 0; i < 8; i++) { - label=lookup_part(tgt->dev_info.disk.scsi_array, part); - p->partitions[i].n_sectors = label->size; - p->partitions[i].offset = label->start; - } - err = SCSI_RET_SUCCESS; - } - break; - - case SCSI_GET_SENSE: { /*_IOR(p, 10, struct extended_sense) */ - scsi_sense_data_t *s; - - s = (scsi_sense_data_t*)tgt->cmd_ptr; - bcopy(s, status, sizeof(*s) + s->u.xtended.add_len - 1); - err = SCSI_RET_SUCCESS; - /* only once */ - bzero(tgt->cmd_ptr, sizeof(scsi_sense_data_t)); - } - break; - - case SCSI_GET_INQUIRY_DATA: { /*_IOR(p, 11, struct inquiry_info) */ - struct mode_sel_sns_params *ms; - - ms = (struct mode_sel_sns_params*)status; - err = scsi_inquiry( tgt, SCSI_INQ_STD_DATA); - if (copyout(tgt->cmd_ptr, ms->msp_addr, sizeof(struct inquiry_info))){ - ret = EFAULT; - goto out; - } - } - break; - - case SCSI_FORMAT_UNIT: { /*_IOW(p, 4, struct format_params) */ - struct format_params *fp; - struct defect_descriptors *df; - unsigned char mode; - unsigned int old_timeout; - - fp = (struct format_params *)status; - df = (struct defect_descriptors*)ior->io_data; - if (fp->fp_length != 0) { - if (copyin(fp->fp_addr, df, sizeof(*df))) { - ret = EFAULT; - goto out; - } - ior->io_count = sizeof(*df); - } else - ior->io_count = 0; - mode = fp->fp_format & SCSI_CMD_FMT_LIST_TYPE; - switch (fp->fp_defects) { - case VENDOR_DEFECTS: - mode |= SCSI_CMD_FMT_FMTDATA|SCSI_CMD_FMT_CMPLIST; - break; - case KNOWN_DEFECTS: - mode |= SCSI_CMD_FMT_FMTDATA; - break; - case NO_DEFECTS: - default: - break; - } - old_timeout = scsi_watchdog_period; - scsi_watchdog_period = 60*60; /* 1 hour should be enough, I hope */ - err = scsi_format_unit( tgt, mode, fp->fp_pattern, - fp->fp_interleave, ior); - scsi_watchdog_period = old_timeout; - /* Make sure we re-read all info afresh */ - tgt->flags = TGT_ALIVE | - (tgt->flags & (TGT_REMOVABLE_MEDIA|TGT_FULLY_PROBED)); - } - break; - - case SCSI_REASSIGN_BLOCK: { /*_IOW(p, 5, struct reassign_params) */ - struct reassign_params *r; - int ndef; - - r = (struct reassign_params*) status; - ndef = r->rp_header.defect_len0 | (r->rp_header.defect_len1 >> 8); - ndef >>= 2; - tgt->ior = ior; - (void) scsi_reassign_blocks( tgt, &r->rp_lbn3, ndef, ior); - iowait(ior); - err = tgt->done; - } - break; - - case SCSI_READ_DEFECT_DATA: { /*_IOW(p, 6, struct read_defect_params) */ - struct read_defect_params *dp; - - dp = (struct read_defect_params *)status; - ior->io_count = ior->io_alloc_size; - if (dp->rdp_alclen > ior->io_count) - dp->rdp_alclen = ior->io_count; - else - ior->io_count = dp->rdp_alclen; - ior->io_op |= IO_READ; - tgt->ior = ior; - err = scsi_read_defect(tgt, dp->rdp_format|0x18, ior); - if (copyout(ior->io_data, dp->rdp_addr, dp->rdp_alclen)) { - ret = EFAULT; - goto out; - } - } - break; - - case SCSI_VERIFY_DATA: { /*_IOW(p, 7, struct verify_params) */ - struct verify_params *v; - unsigned int old_timeout; - - old_timeout = scsi_watchdog_period; - scsi_watchdog_period = 5*60; /* 5 mins enough, I hope */ - v = (struct verify_params *)status; - ior->io_count = 0; - err = scdisk_verify( tgt, v->vp_lbn, v->vp_length, ior); - scsi_watchdog_period = old_timeout; - } - break; - - case SCSI_MODE_SELECT: { /*_IOW(p, 8, struct mode_sel_sns_params) */ - struct mode_sel_sns_params *ms; - - ms = (struct mode_sel_sns_params*)status; - if(copyin(ms->msp_addr, ior->io_data, ms->msp_length)) { - ret = EFAULT; - goto out; - } - err = scdisk_mode_select( tgt, DEV_BSIZE, ior, ior->io_data, - ms->msp_length, ms->msp_setps); - } - break; - - case SCSI_MODE_SENSE: { /*_IOWR(p, 9, struct mode_sel_sns_params) */ - struct mode_sel_sns_params *ms; - unsigned char pagecode; - - ms = (struct mode_sel_sns_params*)status; - pagecode = (ms->msp_pgcode & 0x3f) | (ms->msp_pgctrl << 6); - err = scsi_mode_sense( tgt, pagecode, ms->msp_length, ior); - if (copyout(tgt->cmd_ptr, ms->msp_addr, ms->msp_length)){ - ret = EFAULT; - goto out; - } - } - break; - } - - ret = (err == SCSI_RET_SUCCESS) ? D_SUCCESS : D_IO_ERROR; - if (ior->io_op & IO_ERROR) - ret = D_IO_ERROR; -out: - brelse(ior); - return ret; -} -#endif /*ULTRIX_COMPAT*/ -#endif /*!MACH_KERNEL*/ - -#ifdef CHECKSUM - -#define SUMSIZE 0x10000 -#define SUMHASH(b) (((b)>>1) & (SUMSIZE - 1)) -struct { - long blockno; - long sum; -} scdisk_checksums[SUMSIZE]; - -void scdisk_checksum(bno, addr, size) - long bno; - register unsigned int *addr; -{ - register int i = size/sizeof(int); - register unsigned int sum = -1; - - while (i-- > 0) - sum ^= *addr++; - scdisk_checksums[SUMHASH(bno)].blockno = bno; - scdisk_checksums[SUMHASH(bno)].sum = sum; -} - -void scdisk_bcheck(bno, addr, size) - long bno; - register unsigned int *addr; -{ - register int i = size/sizeof(int); - register unsigned int sum = -1; - unsigned int *start = addr; - - if (scdisk_checksums[SUMHASH(bno)].blockno != bno) { -if (scsi_debug) printf("No checksum for block x%x\n", bno); - return; - } - - while (i-- > 0) - sum ^= *addr++; - - if (scdisk_checksums[SUMHASH(bno)].sum != sum) { - printf("Bad checksum (x%x != x%x), bno x%x size x%x at x%x\n", - sum, - scdisk_checksums[bno & (SUMSIZE - 1)].sum, - bno, size, start); - gimmeabreak(); - scdisk_checksums[SUMHASH(bno)].sum = sum; - } -} - - -#endif CHECKSUM - -/*#define PERF */ -#ifdef PERF -int test_read_size = 512; -int test_read_skew = 12; -int test_read_skew_min = 0; -int test_read_nreads = 1000; -int test_read_bdev = 0; - -#include <sys/time.h> - -void test_read(max) -{ - int i, ssk, usecs; - struct timeval start, stop; - - if (max == 0) - max = test_read_skew + 1; - ssk = test_read_skew; - for (i = test_read_skew_min; i < max; i++){ - test_read_skew = i; - - start = time; - read_test(); - stop = time; - - usecs = stop.tv_usec - start.tv_usec; - if (usecs < 0) { - stop.tv_sec -= 1; - usecs += 1000000; - } - printf("Skew %3d size %d count %d time %3d sec %d us\n", - i, test_read_size, test_read_nreads, - stop.tv_sec - start.tv_sec, usecs); - } - test_read_skew = ssk; -} - -void read_test() -{ - static int buffer[(8192*2)/sizeof(int)]; - struct io_req io; - register int i, rec; - - bzero(&io, sizeof(io)); - io.io_unit = test_read_bdev; - io.io_op = IO_READ; - io.io_count = test_read_size; - io.io_data = (char*) buffer; - - for (rec = 0, i = 0; i < test_read_nreads; i++) { - io.io_op = IO_READ; - io.io_recnum = rec; - scdisk_strategy(&io); - rec += test_read_skew; - iowait(&io); - } -} - -void tur_test() -{ - struct io_req io; - register int i; - char *a, *b; - struct timeval start, stop; - - bzero(&io, sizeof(io)); - io.io_unit = test_read_bdev; - io.io_data = (char*)&io;/*unused but kernel space*/ - - start = time; - for (i = 0; i < test_read_nreads; i++) { - io.io_op = IO_INTERNAL; - rz_check(io.io_unit, &a, &b); - scsi_test_unit_ready(b,&io); - } - stop = time; - i = stop.tv_usec - start.tv_usec; - if (i < 0) { - stop.tv_sec -= 1; - i += 1000000; - } - printf("%d test-unit-ready took %3d sec %d us\n", - test_read_nreads, - stop.tv_sec - start.tv_sec, i); -} - -#endif PERF - -/*#define WDEBUG*/ -#ifdef WDEBUG - -int buggo_write_size = 8192; -int buggo_dev = 2; /* rz0b */ /* changed by KTVM from 1 (still b) */ -int buggo_out_buffer[8192/2]; -int buggo_in_buffer[8192/2]; -int buggotest(n, pattern, verbose) -{ - struct io_req io; - register int i, rec; - - if (n <= 0) - n = 1; - - if(pattern) - for (i = 0; i < buggo_write_size/4; i++) - buggo_out_buffer[i] = i + pattern; - - for (i = 0; i < n; i++) { - register int j; - - buggo_out_buffer[0] = i + pattern; - buggo_out_buffer[(buggo_write_size/4)-1] = i + pattern; - bzero(&io, sizeof(io)); - io.io_unit = buggo_dev; - io.io_data = (char*)buggo_out_buffer; - io.io_op = IO_WRITE; - io.io_count = buggo_write_size; - io.io_recnum = i % 1024; - scdisk_strategy(&io); - - bzero(buggo_in_buffer, sizeof(buggo_in_buffer)); - iowait(&io); - - if (verbose) - printf("Done write with %x", io.io_error); - - bzero(&io, sizeof(io)); - io.io_unit = buggo_dev; - io.io_data = (char*)buggo_in_buffer; - io.io_op = IO_READ; - io.io_count = buggo_write_size; - io.io_recnum = i % 1024; - scdisk_strategy(&io); - iowait(&io); - - if (verbose) - printf("Done read with %x", io.io_error); - - for (j = 0; j < buggo_write_size/4; j++) - if (buggo_out_buffer[j] != buggo_in_buffer[j]){ - printf("Difference at %d-th word: %x %x\n", - buggo_out_buffer[j], buggo_in_buffer[j]); - return i; - } - } - printf("Test ok\n"); - return n; -} -#endif WDEBUG -#endif /* NSCSI > 0 */ diff --git a/scsi/rz_disk_bbr.c b/scsi/rz_disk_bbr.c deleted file mode 100644 index 9d87675..0000000 --- a/scsi/rz_disk_bbr.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: rz_disk_bbr.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 4/91 - * - * Top layer of the SCSI driver: interface with the MI. - * This file contains bad-block management functions - * (retry, replace) for disk-like devices. - */ - -#include <mach/std_types.h> -#include <scsi/compat_30.h> - -#include <scsi/scsi.h> -#include <scsi/scsi_defs.h> -#include <scsi/rz.h> - -#if (NSCSI > 0) - -int scsi_bbr_retries = 10; - -#define BBR_ACTION_COMPLETE 1 -#define BBR_ACTION_RETRY_READ 2 -#define BBR_ACTION_REASSIGN 3 -#define BBR_ACTION_COPY 4 -#define BBR_ACTION_VERIFY 5 - -static void make_msf(); /* forward */ - -/* - * Bad block replacement routine, invoked on - * unrecovereable disk read/write errors. - */ -boolean_t -scdisk_bad_block_repl(tgt, blockno) - target_info_t *tgt; - unsigned int blockno; -{ - register io_req_t ior = tgt->ior; - - if (scsi_no_automatic_bbr || (ior->io_op & IO_INTERNAL)) - return FALSE; - - /* signal we took over */ - tgt->flags |= TGT_BBR_ACTIVE; - - printf("%s", "Attempting bad block replacement.."); - - tgt->dev_info.disk.b.badblockno = blockno; - tgt->dev_info.disk.b.retry_count = 0; - - tgt->dev_info.disk.b.save_rec = ior->io_recnum; - tgt->dev_info.disk.b.save_addr = ior->io_data; - tgt->dev_info.disk.b.save_count = ior->io_count; - tgt->dev_info.disk.b.save_resid = ior->io_residual; - - /* - * On a write all we need is to rewire the offending block. - * Note that the sense data identified precisely which 512 sector - * is bad. At the end we'll retry the entire write, so if there - * is more than one bad sector involved they will be handled one - * at a time. - */ - if ((ior->io_op & IO_READ) == 0) { - char msf[sizeof(int)]; - ior->io_temporary = BBR_ACTION_COMPLETE; - printf("%s", "just reassign.."); - make_msf(msf,blockno); - scsi_reassign_blocks( tgt, msf, 1, ior); - } else - /* - * This is more complicated. We asked for N bytes, and somewhere - * in there there is a chunk of bad data. First off, we should retry - * at least a couple of times to retrieve that data [yes the drive - * should have done its best already so what]. If that fails we - * should recover as much good data as possible (before the bad one). - */ - { - ior->io_temporary = BBR_ACTION_RETRY_READ; - printf("%s", "retry read.."); - ior->io_residual = 0; - scdisk_start_rw(tgt, ior); - } - - return TRUE; -} - -static -void make_msf(buf,val) - unsigned char *buf; - unsigned int val; -{ - *buf++ = val >> 24; - *buf++ = val >> 16; - *buf++ = val >> 8; - *buf++ = val >> 0; -} - -/* - * This effectively replaces the strategy routine during bbr. - */ -void scdisk_bbr_start( tgt, done) - target_info_t *tgt; - boolean_t done; -{ - register io_req_t ior = tgt->ior; - char *msg; - - switch (ior->io_temporary) { - - case BBR_ACTION_COMPLETE: - - /* all done, either way */ -fin: - tgt->flags &= ~TGT_BBR_ACTIVE; - ior->io_recnum = tgt->dev_info.disk.b.save_rec; - ior->io_data = tgt->dev_info.disk.b.save_addr; - ior->io_count = tgt->dev_info.disk.b.save_count; - ior->io_residual = tgt->dev_info.disk.b.save_resid; - - if (tgt->done == SCSI_RET_SUCCESS) { - /* restart normal life */ - register unsigned int xferred; - if (xferred = ior->io_residual) { - ior->io_data -= xferred; - ior->io_count += xferred; - ior->io_recnum -= xferred / tgt->block_size; - ior->io_residual = 0; - } - /* from the beginning */ - ior->io_error = 0; - msg = "done, restarting."; - } else { - /* we could not fix it. Tell user and give up */ - tgt->ior = ior->io_next; - iodone(ior); - msg = "done, but could not recover."; - } - - printf("%s\n", msg); - scdisk_start( tgt, FALSE); - return; - - case BBR_ACTION_RETRY_READ: - - /* see if retry worked, if not do it again */ - if (tgt->done == SCSI_RET_SUCCESS) { - char msf[sizeof(int)]; - - /* whew, retry worked. Now rewire that bad block - * and don't forget to copy the good data over */ - - tgt->dev_info.disk.b.retry_count = 0; - printf("%s", "ok now, reassign.."); - ior->io_temporary = BBR_ACTION_COPY; - make_msf(msf, tgt->dev_info.disk.b.badblockno); - scsi_reassign_blocks( tgt, msf, 1, ior); - return; - } - if (tgt->dev_info.disk.b.retry_count++ < scsi_bbr_retries) { - scdisk_start_rw( tgt, ior); - return; - } - /* retrying was hopeless. Leave the bad block there for maintainance */ - /* because we do not know what to write on it */ - printf("%s%d%s", "failed after ", scsi_bbr_retries, " retries.."); - goto fin; - - - case BBR_ACTION_COPY: - - /* retrying succeded and we rewired the bad block. */ - if (tgt->done == SCSI_RET_SUCCESS) { - unsigned int tmp; - struct diskpart *label; - - printf("%s", "ok, rewrite.."); - - /* writeback only the bad sector */ - - /* map blockno back to partition offset */ -/* !!! partition code changes: */ - tmp = rzpartition(ior->io_unit); -/* label=lookup_part(array, tmp +1); */ - tmp = tgt->dev_info.disk.b.badblockno - -/* label->start; */ -/* #if 0 */ - tgt->dev_info.disk.l.d_partitions[tmp].p_offset; -/* #endif 0 */ - ior->io_data += (tmp - ior->io_recnum) * tgt->block_size; - ior->io_recnum = tmp; - ior->io_count = tgt->block_size; - ior->io_op &= ~IO_READ; - - ior->io_temporary = BBR_ACTION_VERIFY; - scdisk_start_rw( tgt, ior); - } else { - - /* either unsupported command, or repl table full */ - printf("%s", "reassign failed (really needs reformatting), "); - ior->io_error = 0; - goto fin; - } - break; - - case BBR_ACTION_VERIFY: - - if (tgt->done == SCSI_RET_SUCCESS) { - ior->io_op |= IO_READ; - goto fin; - } - - if (tgt->dev_info.disk.b.retry_count++ > scsi_bbr_retries) { - printf("%s%d%s", "failed after ", - scsi_bbr_retries, " retries.."); - ior->io_op |= IO_READ; - goto fin; - } - - /* retry, we are *this* close to success.. */ - scdisk_start_rw( tgt, ior); - - break; - - case BBR_ACTION_REASSIGN: - - /* if we wanted to issue the reassign multiple times */ - /* XXX unimplemented XXX */ - - default: /* snafu */ - panic("scdisk_bbr_start"); - } -} -#endif /* NSCSI > 0 */ diff --git a/scsi/rz_host.c b/scsi/rz_host.c deleted file mode 100644 index 94ccd81..0000000 --- a/scsi/rz_host.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: rz_host.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 7/91 - * - * Top layer of the SCSI driver: interface with the MI. - * This file contains operations specific to CPU-like devices. - * - * We handle here the case of other hosts that are capable of - * sophisticated host-to-host communication protocols, we make - * them look like... you'll see. - * - * There are two sides of the coin here: when we take the initiative - * and when the other host does it. Code for handling both cases is - * provided in this one file. - */ - -#include <mach/std_types.h> -#include <machine/machspl.h> /* spl definitions */ -#include <scsi/compat_30.h> - -#include <scsi/scsi.h> -#include <scsi/scsi_defs.h> -#include <scsi/rz.h> - -#if (NSCSI > 0) -/* Since we have invented a new "device" this cannot go into the - the 'official' scsi_devsw table. Too bad. */ - -extern char *schost_name(); -extern scsi_ret_t - schost_open(), schost_close(); -extern int schost_strategy(); -extern void schost_start(); - -scsi_devsw_t scsi_host = { - schost_name, 0, schost_open, schost_close, schost_strategy, - schost_start, 0, 0 -}; - -char *schost_name(internal) - boolean_t internal; -{ - return internal ? "sh" : "host"; -} - -scsi_ret_t -schost_open(tgt) - target_info_t *tgt; -{ - return SCSI_RET_SUCCESS; /* XXX if this is it, drop it */ -} - -scsi_ret_t -schost_close(tgt) - target_info_t *tgt; -{ - return SCSI_RET_SUCCESS; /* XXX if this is it, drop it */ -} - -schost_strategy(ior) - register io_req_t ior; -{ - return rz_simpleq_strategy( ior, schost_start); -} - -void -schost_start( tgt, done) - target_info_t *tgt; - boolean_t done; -{ - io_req_t head, ior; - scsi_ret_t ret; - - if (done || (!tgt->dev_info.cpu.req_pending)) { - sccpu_start( tgt, done); - return; - } - - ior = tgt->ior; -} - -#endif /* NSCSI > 0 */ diff --git a/scsi/rz_labels.h b/scsi/rz_labels.h deleted file mode 100644 index 6ffaa11..0000000 --- a/scsi/rz_labels.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: rz_labels.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Definitions of various vendor's disk label formats. - */ - -/* modified by Kevin T. Van Maren for the unified partition code */ - -#ifndef _RZ_LABELS_H_ -#define _RZ_LABELS_H_ - -/* - * This function looks for, and converts to BSD format - * a vendor's label. It is only called if we did not - * find a standard BSD label on the disk pack. - */ -extern boolean_t rz_vendor_label(); - -/* - * Definition of the DEC disk label, - * which is located (you guessed it) - * at the end of the 4.3 superblock. - */ - -struct dec_partition_info { - unsigned int n_sectors; /* how big the partition is */ - unsigned int offset; /* sector no. of start of part. */ -}; - -typedef struct { - int magic; -# define DEC_LABEL_MAGIC 0x032957 - int in_use; - struct dec_partition_info partitions[8]; -} dec_label_t; - -/* - * Physical location on disk. - * This is independent of the filesystem we use, - * although of course we'll be in trouble if we - * screwup the 4.3 SBLOCK.. - */ - -#define DEC_LABEL_BYTE_OFFSET ((2*8192)-sizeof(dec_label_t)) - - -/* - * Definitions for the primary boot information - * This is common, cuz the prom knows it. - */ - -typedef struct { - int pad[2]; - unsigned int magic; -# define DEC_BOOT0_MAGIC 0x2757a - int mode; - unsigned int phys_base; - unsigned int virt_base; - unsigned int n_sectors; - unsigned int start_sector; -} dec_boot0_t; - -typedef struct { - dec_boot0_t vax_boot; - /* BSD label still fits in pad */ - char pad[0x1e0-sizeof(dec_boot0_t)]; - unsigned long block_count; - unsigned long starting_lbn; - unsigned long flags; - unsigned long checksum; /* add cmpl-2 all but here */ -} alpha_boot0_t; - -/* - * Definition of the Omron disk label, - * which is located at sector 0. It - * _is_ sector 0, actually. - */ -struct omron_partition_info { - unsigned long offset; - unsigned long n_sectors; -}; - -typedef struct { - char packname[128]; /* in ascii */ - - char pad[512-(128+8*8+11*2+4)]; - - unsigned short badchk; /* checksum of bad track */ - unsigned long maxblk; /* # of total logical blocks */ - unsigned short dtype; /* disk drive type */ - unsigned short ndisk; /* # of disk drives */ - unsigned short ncyl; /* # of data cylinders */ - unsigned short acyl; /* # of alternate cylinders */ - unsigned short nhead; /* # of heads in this partition */ - unsigned short nsect; /* # of 512 byte sectors per track */ - unsigned short bhead; /* identifies proper label locations */ - unsigned short ppart; /* physical partition # */ - struct omron_partition_info - partitions[8]; - - unsigned short magic; /* identifies this label format */ -# define OMRON_LABEL_MAGIC 0xdabe - - unsigned short cksum; /* xor checksum of sector */ - -} omron_label_t; - -/* - * Physical location on disk. - */ - -#define OMRON_LABEL_BYTE_OFFSET 0 - - -/* - * Definition of the i386AT disk label, which lives inside sector 0. - * This is the info the BIOS knows about, which we use for bootstrapping. - * It is common across all disks known to BIOS. - */ - -struct bios_partition_info { - - unsigned char bootid; /* bootable or not */ -# define BIOS_BOOTABLE 128 - - unsigned char beghead;/* beginning head, sector, cylinder */ - unsigned char begsect;/* begcyl is a 10-bit number. High 2 bits */ - unsigned char begcyl; /* are in begsect. */ - - unsigned char systid; /* filesystem type */ -# define UNIXOS 99 /* GNU HURD? */ -# define BSDOS 165 /* 386BSD */ -# define LINUXSWAP 130 -# define LINUXOS 131 -# define DOS_EXTENDED 05 /* container for logical partitions */ - -# define HPFS 07 /* OS/2 Native */ -# define OS_2_BOOT 10 /* OS/2 Boot Manager */ -# define DOS_12 01 /* 12 bit FAT */ -# define DOS_16_OLD 04 /* < 32MB */ -# define DOS_16 06 /* >= 32MB (#4 not used anymore) */ - - /* these numbers can't be trusted because */ - /* of newer, larger drives */ - unsigned char endhead;/* ending head, sector, cylinder */ - unsigned char endsect;/* endcyl is a 10-bit number. High 2 bits */ - unsigned char endcyl; /* are in endsect. */ - - unsigned long offset; - unsigned long n_sectors; -}; - -typedef struct { -/* struct bios_partition_info bogus compiler alignes wrong - partitions[4]; -*/ - char partitions[4*sizeof(struct bios_partition_info)]; - unsigned short magic; -# define BIOS_LABEL_MAGIC 0xaa55 -} bios_label_t; - -/* - * Physical location on disk. - */ - -#define BIOS_LABEL_BYTE_OFFSET 446 - -/* - * Definitions for the primary boot information - * This _is_ block 0 - */ - -#define BIOS_BOOT0_SIZE BIOS_LABEL_BYTE_OFFSET - -typedef struct { - char boot0[BIOS_BOOT0_SIZE]; /* boot code */ -/* bios_label_t label; bogus compiler alignes wrong */ - char label[sizeof(bios_label_t)]; -} bios_boot0_t; - -/* Moved from i386at/nhdreg.h */ -#define PDLOCATION 29 /* VTOC sector */ - - -/* these are the partition types that can contain sub-partitions */ -/* enum types... */ -#define DISKPART_NONE 0 /* smallest piece flag !?! */ -#define DISKPART_DOS 1 -#define DISKPART_BSD 2 -#define DISKPART_VTOC 3 -#define DISKPART_OMRON 4 -#define DISKPART_DEC 5 /* VAX disks? */ -#define DISKPART_UNKNOWN 99 - - - -/* for NEW partition code */ -/* this is the basic partition structure. an array of these is - filled, with element 0 being the whole drive, element 1-n being - the n top-level partitions, followed by 0+ groups of 1+ sub-partitions. */ -typedef struct diskpart { - short type; /* DISKPART_xxx (see above) */ - short fsys; /* file system (if known) */ - int nsubs; /* number of sub-slices */ - struct diskpart *subs; /* pointer to the sub-partitions */ - int start; /* relative to the start of the DRIVE */ - int size; /* # sectors in this piece */ -} diskpart; - -int get_only_partition(void *driver_info, int (*bottom_read_fun)(), - struct diskpart *array, int array_size, - int disk_size, char *drive_name); - -struct diskpart *lookup_part(struct diskpart *array, int dev_number); -#endif _RZ_LABELS_H_ - diff --git a/scsi/rz_tape.c b/scsi/rz_tape.c deleted file mode 100644 index 1d27722..0000000 --- a/scsi/rz_tape.c +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: rz_tape.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Top layer of the SCSI driver: interface with the MI. - * This file contains operations specific to TAPE-like devices. - */ - -#include <mach/std_types.h> -#include <scsi/compat_30.h> - -#include <sys/ioctl.h> -#ifdef MACH_KERNEL -#include <device/tape_status.h> -#else /*MACH_KERNEL*/ -#include <mips/PMAX/tape_status.h> -#endif /*MACH_KERNEL*/ - -#include <scsi/scsi.h> -#include <scsi/scsi_defs.h> -#include <scsi/rz.h> - -#if (NSCSI > 0) - - -void sctape_start(); /* forward */ - -int scsi_tape_timeout = 5*60; /* secs, tk50 is slow when positioning far apart */ - -int sctape_open(tgt, req) - target_info_t *tgt; - io_req_t req; -{ - io_return_t ret; - io_req_t ior; - int i; - scsi_mode_sense_data_t *mod; - -#ifdef MACH_KERNEL - req->io_device->flag |= D_EXCL_OPEN; -#endif /*MACH_KERNEL*/ - - /* Preferably allow tapes to disconnect */ - if (BGET(scsi_might_disconnect,(unsigned char)tgt->masterno,tgt->target_id)) - BSET(scsi_should_disconnect,(unsigned char)tgt->masterno,tgt->target_id); - - /* - * Dummy ior for proper sync purposes - */ - io_req_alloc(ior,0); - ior->io_count = 0; - - /* - * Do a mode sense first, some drives might be picky - * about changing params [even if the standard might - * say otherwise, sigh.] - */ - do { - ior->io_op = IO_INTERNAL; - ior->io_next = 0; - ior->io_error = 0; - ret = scsi_mode_sense(tgt, 0, 32, ior); - } while (ret == SCSI_RET_RETRY); - - mod = (scsi_mode_sense_data_t *)tgt->cmd_ptr; - if (scsi_debug) { - int p[5]; - bcopy((char*)mod, (char*)p, sizeof(p)); - printf("[modsns(%x): x%x x%x x%x x%x x%x]", ret, - p[0], p[1], p[2], p[3], p[4]); - } - if (ret == SCSI_RET_DEVICE_DOWN) - goto out; - if (ret == SCSI_RET_SUCCESS) { - tgt->dev_info.tape.read_only = mod->wp; - tgt->dev_info.tape.speed = mod->speed; - tgt->dev_info.tape.density = mod->bdesc[0].density_code; - } /* else they all default sensibly, using zeroes */ - - /* Some tapes have limits on record-length */ -again: - ior->io_op = IO_INTERNAL; - ior->io_next = 0; - ior->io_error = 0; - ret = scsi_read_block_limits( tgt, ior); - if (ret == SCSI_RET_RETRY) goto again; - if (!ior->io_error && (ret == SCSI_RET_SUCCESS)) { - scsi_blimits_data_t *lim; - int maxl; - - lim = (scsi_blimits_data_t *) tgt->cmd_ptr; - - tgt->block_size = (lim->minlen_msb << 8) | - lim->minlen_lsb; - - maxl = (lim->maxlen_msb << 16) | - (lim->maxlen_sb << 8) | - lim->maxlen_lsb; - if (maxl == 0) - maxl = (unsigned)-1; - tgt->dev_info.tape.maxreclen = maxl; - tgt->dev_info.tape.fixed_size = (maxl == tgt->block_size); - } else { - /* let the user worry about it */ - /* default: tgt->block_size = 1; */ - tgt->dev_info.tape.maxreclen = (unsigned)-1; - tgt->dev_info.tape.fixed_size = FALSE; - } - - /* Try hard to do a mode select */ - for (i = 0; i < 5; i++) { - ior->io_op = IO_INTERNAL; - ior->io_error = 0; - ret = sctape_mode_select(tgt, 0, 0, FALSE, ior); - if (ret == SCSI_RET_SUCCESS) - break; - } - if (scsi_watchdog_period < scsi_tape_timeout) - scsi_watchdog_period += scsi_tape_timeout; - -#if 0 /* this might imply rewind, which we do not want, although yes, .. */ - /* we want the tape loaded */ - ior->io_op = IO_INTERNAL; - ior->io_next = 0; - ior->io_error = 0; - ret = scsi_start_unit(tgt, SCSI_CMD_SS_START, ior); -#endif - req->io_device->bsize = tgt->block_size; -out: - io_req_free(ior); - return ret; -} - - -io_return_t sctape_close(tgt) - target_info_t *tgt; -{ - io_return_t ret = SCSI_RET_SUCCESS; - io_req_t ior; - - /* - * Dummy ior for proper sync purposes - */ - io_req_alloc(ior,0); - ior->io_op = IO_INTERNAL; - ior->io_next = 0; - ior->io_count = 0; - - if (tgt->ior) printf("TAPE: Close with pending requests ?? \n"); - - /* write a filemark if we xtnded/truncated the tape */ - if (tgt->flags & TGT_WRITTEN_TO) { - tgt->ior = ior; - ior->io_error = 0; - ret = scsi_write_filemarks(tgt, 2, ior); - if (ret != SCSI_RET_SUCCESS) - printf("%s%d: wfmark failed x%x\n", - (*tgt->dev_ops->driver_name)(TRUE), tgt->target_id, ret); - /* - * Don't bother repositioning if we'll rewind it - */ - if (tgt->flags & TGT_REWIND_ON_CLOSE) - goto rew; -retry: - tgt->ior = ior; - ior->io_op = IO_INTERNAL; - ior->io_error = 0; - ior->io_next = 0; - ret = scsi_space(tgt, SCSI_CMD_SP_FIL, -1, ior); - if (ret != SCSI_RET_SUCCESS) { - if (ret == SCSI_RET_RETRY) { - timeout(wakeup, tgt, hz); - await(tgt); - goto retry; - } - printf("%s%d: bspfile failed x%x\n", - (*tgt->dev_ops->driver_name)(TRUE), tgt->target_id, ret); - } - } -rew: - if (tgt->flags & TGT_REWIND_ON_CLOSE) { - /* Rewind tape */ - ior->io_error = 0; - ior->io_op = IO_INTERNAL; - ior->io_error = 0; - tgt->ior = ior; - (void) scsi_rewind(tgt, ior, FALSE); - iowait(ior); - if (tgt->done == SCSI_RET_RETRY) { - timeout(wakeup, tgt, 5*hz); - await(tgt); - goto rew; - } - } - io_req_free(ior); - - tgt->flags &= ~(TGT_ONLINE|TGT_WRITTEN_TO|TGT_REWIND_ON_CLOSE); - return ret; -} - -int sctape_strategy(ior) - register io_req_t ior; -{ - target_info_t *tgt; - register int i = ior->io_unit; - - tgt = scsi_softc[rzcontroller(i)]->target[rzslave(i)]; - - if (((ior->io_op & IO_READ) == 0) && - tgt->dev_info.tape.read_only) { - ior->io_error = D_INVALID_OPERATION; - ior->io_op |= IO_ERROR; - ior->io_residual = ior->io_count; - iodone(ior); - return ior->io_error; - } - - return rz_simpleq_strategy( ior, sctape_start); -} - -static void -do_residue(ior, sns, bsize) - io_req_t ior; - scsi_sense_data_t *sns; - int bsize; -{ - int residue; - - /* Not an error situation */ - ior->io_error = 0; - ior->io_op &= ~IO_ERROR; - - if (!sns->addr_valid) { - ior->io_residual = ior->io_count; - return; - } - - residue = sns->u.xtended.info0 << 24 | - sns->u.xtended.info1 << 16 | - sns->u.xtended.info2 << 8 | - sns->u.xtended.info3; - /* fixed ? */ - residue *= bsize; - /* - * NOTE: residue == requested - actual - * We only care if > 0 - */ - if (residue < 0) residue = 0;/* sanity */ - ior->io_residual += residue; -} - -void sctape_start( tgt, done) - target_info_t *tgt; - boolean_t done; -{ - io_req_t head, ior = tgt->ior; - - if (ior == 0) - return; - - if (done) { - - /* see if we must retry */ - if ((tgt->done == SCSI_RET_RETRY) && - ((ior->io_op & IO_INTERNAL) == 0)) { - delay(1000000);/*XXX*/ - goto start; - } else - /* got a bus reset ? ouch, that hurts */ - if (tgt->done == (SCSI_RET_ABORTED|SCSI_RET_RETRY)) { - /* - * we really cannot retry because the tape position - * is lost. - */ - printf("Lost tape position\n"); - ior->io_error = D_IO_ERROR; - ior->io_op |= IO_ERROR; - } else - - /* check completion status */ - - if (tgt->cur_cmd == SCSI_CMD_REQUEST_SENSE) { - scsi_sense_data_t *sns; - - ior->io_op = ior->io_temporary; - ior->io_error = D_IO_ERROR; - ior->io_op |= IO_ERROR; - - sns = (scsi_sense_data_t *)tgt->cmd_ptr; - - if (scsi_debug) - scsi_print_sense_data(sns); - - if (scsi_check_sense_data(tgt, sns)) { - if (sns->u.xtended.ili) { - if (ior->io_op & IO_READ) { - do_residue(ior, sns, tgt->block_size); - if (scsi_debug) - printf("Tape Short Read (%d)\n", - ior->io_residual); - } - } else if (sns->u.xtended.eom) { - do_residue(ior, sns, tgt->block_size); - if (scsi_debug) - printf("End of Physical Tape!\n"); - } else if (sns->u.xtended.fm) { - do_residue(ior, sns, tgt->block_size); - if (scsi_debug) - printf("File Mark\n"); - } - } - } - - else if (tgt->done != SCSI_RET_SUCCESS) { - - if (tgt->done == SCSI_RET_NEED_SENSE) { - - ior->io_temporary = ior->io_op; - ior->io_op = IO_INTERNAL; - if (scsi_debug) - printf("[NeedSns x%x x%x]", ior->io_residual, ior->io_count); - scsi_request_sense(tgt, ior, 0); - return; - - } else if (tgt->done == SCSI_RET_RETRY) { - /* only retry here READs and WRITEs */ - if ((ior->io_op & IO_INTERNAL) == 0) { - ior->io_residual = 0; - goto start; - } else{ - ior->io_error = D_WOULD_BLOCK; - ior->io_op |= IO_ERROR; - } - } else { - ior->io_error = D_IO_ERROR; - ior->io_op |= IO_ERROR; - } - } - - if (scsi_debug) - printf("[Resid x%x]", ior->io_residual); - - /* dequeue next one */ - head = ior; - - simple_lock(&tgt->target_lock); - ior = head->io_next; - tgt->ior = ior; - if (ior) - ior->io_prev = head->io_prev; - simple_unlock(&tgt->target_lock); - - iodone(head); - - if (ior == 0) - return; - } - ior->io_residual = 0; -start: - if (ior->io_op & IO_READ) { - tgt->flags &= ~TGT_WRITTEN_TO; - sctape_read( tgt, ior ); - } else if ((ior->io_op & IO_INTERNAL) == 0) { - tgt->flags |= TGT_WRITTEN_TO; - sctape_write( tgt, ior ); - } -} - -io_return_t -sctape_get_status( dev, tgt, flavor, status, status_count) - int dev; - target_info_t *tgt; - dev_flavor_t flavor; - dev_status_t status; - natural_t *status_count; -{ - switch (flavor) { - case DEV_GET_SIZE: - - status[DEV_GET_SIZE_DEVICE_SIZE] = 0; - status[DEV_GET_SIZE_RECORD_SIZE] = tgt->block_size; - *status_count = DEV_GET_SIZE_COUNT; - break; - case TAPE_STATUS: { - struct tape_status *ts = (struct tape_status *) status; - - ts->mt_type = MT_ISSCSI; - ts->speed = tgt->dev_info.tape.speed; - ts->density = tgt->dev_info.tape.density; - ts->flags = (tgt->flags & TGT_REWIND_ON_CLOSE) ? - TAPE_FLG_REWIND : 0; - if (tgt->dev_info.tape.read_only) - ts->flags |= TAPE_FLG_WP; -#ifdef MACH_KERNEL - *status_count = TAPE_STATUS_COUNT; -#endif - - break; - } - /* U*x compat */ - case MTIOCGET: { - struct mtget *g = (struct mtget *) status; - - bzero(g, sizeof(struct mtget)); - g->mt_type = 0x7; /* Ultrix compat */ -#ifdef MACH_KERNEL - *status_count = sizeof(struct mtget)/sizeof(int); -#endif - break; - } - default: - return D_INVALID_OPERATION; - } - return D_SUCCESS; -} - -io_return_t -sctape_set_status( dev, tgt, flavor, status, status_count) - int dev; - target_info_t *tgt; - dev_flavor_t flavor; - dev_status_t status; - natural_t status_count; -{ - scsi_ret_t ret; - - switch (flavor) { - case TAPE_STATUS: { - struct tape_status *ts = (struct tape_status *) status; - if (ts->flags & TAPE_FLG_REWIND) - tgt->flags |= TGT_REWIND_ON_CLOSE; - else - tgt->flags &= ~TGT_REWIND_ON_CLOSE; - - if (ts->speed || ts->density) { - unsigned int ospeed, odensity; - io_req_t ior; - - io_req_alloc(ior,0); - ior->io_op = IO_INTERNAL; - ior->io_error = 0; - ior->io_next = 0; - ior->io_count = 0; - - ospeed = tgt->dev_info.tape.speed; - odensity = tgt->dev_info.tape.density; - tgt->dev_info.tape.speed = ts->speed; - tgt->dev_info.tape.density = ts->density; - - ret = sctape_mode_select(tgt, 0, 0, (ospeed == ts->speed), ior); - if (ret != SCSI_RET_SUCCESS) { - tgt->dev_info.tape.speed = ospeed; - tgt->dev_info.tape.density = odensity; - } - - io_req_free(ior); - } - - break; - } - /* U*x compat */ - case MTIOCTOP: { - struct tape_params *mt = (struct tape_params *) status; - io_req_t ior; - - if (scsi_debug) - printf("[sctape_sstatus: %x %x %x]\n", - flavor, mt->mt_operation, mt->mt_repeat_count); - - io_req_alloc(ior,0); -retry: - ior->io_count = 0; - ior->io_op = IO_INTERNAL; - ior->io_error = 0; - ior->io_next = 0; - tgt->ior = ior; - - /* compat: in U*x it is a short */ - switch ((short)(mt->mt_operation)) { - case MTWEOF: /* write an end-of-file record */ - ret = scsi_write_filemarks(tgt, mt->mt_repeat_count, ior); - break; - case MTFSF: /* forward space file */ - ret = scsi_space(tgt, SCSI_CMD_SP_FIL, mt->mt_repeat_count, ior); - break; - case MTBSF: /* backward space file */ - ret = scsi_space(tgt, SCSI_CMD_SP_FIL, -mt->mt_repeat_count,ior); - break; - case MTFSR: /* forward space record */ - ret = scsi_space(tgt, SCSI_CMD_SP_BLOCKS, mt->mt_repeat_count, ior); - break; - case MTBSR: /* backward space record */ - ret = scsi_space(tgt, SCSI_CMD_SP_BLOCKS, -mt->mt_repeat_count, ior); - break; - case MTREW: /* rewind */ - case MTOFFL: /* rewind and put the drive offline */ - ret = scsi_rewind(tgt, ior, TRUE); - iowait(ior); - if ((short)(mt->mt_operation) == MTREW) break; - ior->io_op = 0; - ior->io_next = 0; - ior->io_error = 0; - (void) scsi_start_unit(tgt, 0, ior); - break; - case MTNOP: /* no operation, sets status only */ - case MTCACHE: /* enable controller cache */ - case MTNOCACHE: /* disable controller cache */ - ret = SCSI_RET_SUCCESS; - break; - default: - tgt->ior = 0; - io_req_free(ior); - return D_INVALID_OPERATION; - } - - if (ret == SCSI_RET_RETRY) { - timeout(wakeup, ior, 5*hz); - await(ior); - goto retry; - } - - io_req_free(ior); - if (ret != SCSI_RET_SUCCESS) - return D_IO_ERROR; - break; - } - case MTIOCIEOT: - case MTIOCEEOT: - default: - return D_INVALID_OPERATION; - } - return D_SUCCESS; -} -#endif /* NSCSI > 0 */ diff --git a/scsi/scsi.c b/scsi/scsi.c deleted file mode 100644 index d4aecf6..0000000 --- a/scsi/scsi.c +++ /dev/null @@ -1,642 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1993-1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 9/90 - * - * Middle layer of the SCSI driver: chip independent functions - * This file contains Controller and Device-independent functions - */ - -#include <scsi.h> - -#if NSCSI > 0 -#include <platforms.h> - -#include <machine/machspl.h> /* spl definitions */ - -#include <mach/std_types.h> -#include <sys/types.h> -#include <scsi/compat_30.h> - -#include <chips/busses.h> -#include <scsi/scsi.h> -#include <scsi/scsi2.h> -#include <scsi/scsi_defs.h> -#include <machine/machspl.h> - - - -#ifdef VAXSTATION -/* We run some of this code on the interrupt stack */ -#undef spl0 -#define spl0() spl1() -#endif /*VAXSTATION*/ - -/* - * Overall driver state - */ - -target_info_t scsi_target_data[NSCSI*8]; /* per target state */ -scsi_softc_t scsi_softc_data[NSCSI]; /* per HBA state */ -scsi_softc_t *scsi_softc[NSCSI]; /* quick access&checking */ - -/* - * If a specific target should NOT be asked to go synchronous - * then its bit in this bitmap should be set. Each SCSI controller - * (Host Bus Adapter) can hold at most 8 targets --> use one - * byte per controller. A bit set to one means NO synchronous. - * Patch with adb if necessary. - */ -unsigned char scsi_no_synchronous_xfer[NSCSI]; - -/* - * For certain targets it is wise to use the long form of the - * read/write commands even if their capacity would not necessitate - * it. Same as above for usage. - */ -unsigned char scsi_use_long_form[NSCSI]; - - -/* - * Control over disconnect-reconnect mode. - */ -unsigned char scsi_might_disconnect[NSCSI] = /* do it if deemed appropriate */ - { 0xff, 0xff, 0xff, 0xff, 0xff};/* Fix by hand viz NSCSI */ -unsigned char scsi_should_disconnect[NSCSI] = /* just do it */ - { 0,}; -unsigned char scsi_initiator_id[NSCSI] = /* our id on the bus(ses) */ - { 7, 7, 7, 7, 7}; - -/* - * Miscellaneus config - */ -boolean_t scsi_exabyte_filemarks = FALSE; /* use short filemarks */ -int scsi_watchdog_period = 10; /* but exabyte needs >=30 for bspace */ -int scsi_delay_after_reset = 1000000;/* microseconds */ -boolean_t scsi_no_automatic_bbr = FALSE; /* revector bad blocks automatically */ - -#ifdef MACH_KERNEL -#else -/* This covers Exabyte's max record size */ -unsigned int scsi_per_target_virtual = 256*1024; -#endif MACH_KERNEL - - -/* - * Device-specific operations are switched off this table - */ - -extern char - *scdisk_name(), *sctape_name(), *scprt_name(), - *sccpu_name(), *scworm_name(), *sccdrom_name(), - *scscn_name(), *scmem_name(), *scjb_name(), *sccomm_name(); -extern void - sctape_optimize(); -extern scsi_ret_t - scdisk_open(), sctape_open(), sctape_close(), - sccomm_open(), sccomm_close(); -extern int - scdisk_strategy(), sctape_strategy(), sccpu_strategy(), - sccomm_strategy(); -extern void - scdisk_start(), sctape_start(), sccpu_start(), sccomm_start(); - -extern io_return_t - scdisk_set_status(), scdisk_get_status(), - sctape_set_status(), sctape_get_status(), - sccomm_set_status(), sccomm_get_status(); - -scsi_devsw_t scsi_devsw[] = { - -/* SCSI_DISK */ { scdisk_name, SCSI_OPTIMIZE_NULL, - scdisk_open, SCSI_CLOSE_NULL, - scdisk_strategy, scdisk_start, - scdisk_get_status, scdisk_set_status }, - -/* SCSI_TAPE */ { sctape_name, sctape_optimize, - sctape_open, sctape_close, - sctape_strategy, sctape_start, - sctape_get_status, sctape_set_status }, - -/* SCSI_PRINTER */ { scprt_name, SCSI_OPTIMIZE_NULL, /*XXX*/}, - -/* SCSI_CPU */ { sccpu_name, SCSI_OPTIMIZE_NULL, - SCSI_OPEN_NULL, SCSI_CLOSE_NULL, - sccpu_strategy, sccpu_start,}, - -/* SCSI_WORM */ { scworm_name, SCSI_OPTIMIZE_NULL, - scdisk_open, SCSI_CLOSE_NULL, - scdisk_strategy, scdisk_start, - scdisk_get_status, scdisk_set_status }, - -/* SCSI_CDROM */ { sccdrom_name, SCSI_OPTIMIZE_NULL, - scdisk_open, SCSI_CLOSE_NULL, - scdisk_strategy, scdisk_start, - scdisk_get_status, scdisk_set_status }, -/* scsi2 */ -/* SCSI_SCANNER */ { scscn_name, SCSI_OPTIMIZE_NULL, /*XXX*/ }, - -/* SCSI_MEMORY */ { scmem_name, SCSI_OPTIMIZE_NULL, - scdisk_open, SCSI_CLOSE_NULL, - scdisk_strategy, scdisk_start, - scdisk_get_status, scdisk_set_status }, - -/* SCSI_J_BOX */ { scjb_name, SCSI_OPTIMIZE_NULL, /*XXX*/ }, - -/* SCSI_COMM */ { sccomm_name, SCSI_OPTIMIZE_NULL, -#if (NCENDATA>0) - sccomm_open, sccomm_close, - sccomm_strategy, sccomm_start, - sccomm_get_status, sccomm_set_status -#endif - }, - 0 -}; - -/* - * Allocation routines for state structures - */ -scsi_softc_t * -scsi_master_alloc(unit, hw) - unsigned unit; - char *hw; -{ - scsi_softc_t *sc; - - if (unit < NSCSI) { - sc = &scsi_softc_data[unit]; - scsi_softc[unit] = sc; - sc->masterno = unit; - sc->hw_state = hw; - return sc; - } - return 0; -} - -target_info_t * -scsi_slave_alloc(unit, slave, hw) - unsigned unit, slave; - char *hw; -{ - target_info_t *tgt; - - tgt = &scsi_target_data[(unit<<3) + slave]; - tgt->hw_state = hw; - tgt->dev_ops = 0; /* later */ - tgt->target_id = slave; - tgt->masterno = unit; - tgt->block_size = 1; /* default */ - tgt->flags = TGT_ALIVE; - tgt->sync_period = 0; - tgt->sync_offset = 0; - simple_lock_init(&tgt->target_lock); - - scsi_softc[unit]->target[slave] = tgt; - return tgt; -} - -void -zero_ior( - io_req_t ior ) -{ - ior->io_next = ior->io_prev = 0; - ior->io_count = 0; - ior->io_op = IO_INTERNAL; - ior->io_error = 0; -} - -/* - * Slave routine: - * See if the slave description (controller, unit, ..) - * matches one of the slaves found during probe - * - * Implementation: - * Send out an INQUIRY command to see what sort of device - * the slave is. - * Notes: - * At this time the driver is fully functional and works - * off interrupts. - * TODO: - * The SCSI2 spec says what exactly must happen: see F.2.3 - */ -int scsi_slave( ui, reg) - struct bus_device *ui; - unsigned reg; -{ - scsi_softc_t *sc = scsi_softc[(unsigned char)ui->ctlr]; - target_info_t *tgt = sc->target[(unsigned char)ui->slave]; - scsi2_inquiry_data_t *inq; - int scsi_std; - int ptype, s; - - if (!tgt || !(tgt->flags & TGT_ALIVE)) - return 0; - - /* Might have scanned already */ - if (tgt->dev_ops) - goto out; - -#ifdef SCSI2 - This is what should happen: - - for all LUNs - INQUIRY - scsi_verify_state (see) - scsi_initialize (see) -#endif SCSI2 - - tgt->unit_no = ui->slave; /* incorrect, but needed early */ - - s = spl0(); /* we need interrupts */ - - if (BGET(scsi_no_synchronous_xfer,(unsigned char)sc->masterno,tgt->target_id)) - tgt->flags |= TGT_DID_SYNCH; - - /* - * Ok, it is time to see what type of device this is, - * send an INQUIRY cmd and wait till done. - * Possibly do the synch negotiation here. - */ - scsi_inquiry(tgt, SCSI_INQ_STD_DATA); - - inq = (scsi2_inquiry_data_t*)tgt->cmd_ptr; - ptype = inq->periph_type; - - switch (ptype) { - case SCSI_CDROM : - tgt->flags |= TGT_READONLY; - /* fall through */ - case SCSI_DISK : - case SCSI_TAPE : - case SCSI_PRINTER : - case SCSI_CPU : - case SCSI_WORM : - case SCSI_SCANNER : - case SCSI_MEMORY : - case SCSI_J_BOX : - case SCSI_COMM : -/* case SCSI_PREPRESS1 : reserved, really - case SCSI_PREPRESS2 : */ - tgt->dev_ops = &scsi_devsw[ptype]; - break; - default: - printf("scsi%d: %s %d (x%x). ", ui->ctlr, - "Unsupported device type at SCSI id", ui->slave, - inq->periph_type); - scsi_print_inquiry((scsi2_inquiry_data_t*)inq, - SCSI_INQ_STD_DATA, 0); - tgt->flags = 0; - splx(s); - return 0; - } - - if (inq->rmb) - tgt->flags |= TGT_REMOVABLE_MEDIA; - - /* - * Tell the user we know this target, then see if we - * can be a bit smart about it. - */ - scsi_print_inquiry((scsi2_inquiry_data_t*)inq, - SCSI_INQ_STD_DATA, tgt->tgt_name); - if (scsi_debug) - scsi_print_inquiry((scsi2_inquiry_data_t*)inq, - SCSI_INQ_STD_DATA, 0); - - /* - * The above says if it currently behaves as a scsi2, - * however scsi1 might just be the default setting. - * The spec say that even if in scsi1 mode the target - * should answer to the full scsi2 inquiry spec. - */ - scsi_std = (inq->ansi == 2 || inq->response_fmt == 2) ? 2 : 1; -#if nosey - if (scsi_std == 2) { - unsigned char supp_pages[256], i; - scsi2_impl_opdef_page_t *impl; - - scsi_inquiry(tgt, SCSI_INQ_SUPP_PAGES); - impl = (scsi2_impl_opdef_page_t *)inq; - npages = impl->page_len - 2; - bcopy(impl->supp_opdef, supp_pages, npages); - - for (i = 0; i < npages; i++) { - scsi_inquiry(tgt, supp_pages[i]); - scsi_print_inquiry(inq, supp_pages[i], 0); - } - } - - if (scsi_std == 2) { - scsi2_impl_opdef_page_t *impl; - int i; - - scsi_inquiry(tgt, SCSI_INQ_IMPL_OPDEF); - impl = (scsi2_impl_opdef_page_t *)inq; - for (i = 0; i < impl->page_len - 2; i++) - if (impl->supp_opdef[i] == SCSI2_OPDEF) { - scsi_change_definition(tgt, SCSI2_OPDEF); - /* if success .. */ - tgt->flags |= TGT_SCSI_2_MODE; - break; - } - } -#endif nosey - - splx(s); -out: - return (strcmp(ui->name, (*tgt->dev_ops->driver_name)(TRUE)) == 0); -} - -#ifdef SCSI2 -scsi_verify_state(...) -{ -verify_state: send test_unit_ready up to 3 times, each time it fails -(with check condition) send a requeste_sense. It is ok to get UNIT ATTENTION -the first time only, NOT READY the second, only GOOD the last time. -If you get BUSY or RESERVATION CONFLICT retry. -} - -scsi_initialize(...) -{ - -initialize: send start_unit with immed=0 (->disconnect), if fails -with check condition send requeste_sense and if "illegal request" -proceed anyways. Retry on BUSY. -Do a verify_state, then -disks: - - mode_sense (current) if ANSI2 or needed by vendor (!!!!) - and if check-condition&illegal-request goto capacity - - mode_sense (changeable) - - if needed do a mode_select (yes, 512) - - read_capacity -tapes: - -} -#endif SCSI2 - -/* - * Attach routine: - * Fill in all the relevant per-slave data and make - * the slave operational. - * - * Implementation: - * Get target's status, start the unit and then - * switch off to device-specific functions to gather - * as much info as possible about the slave. - */ -void scsi_attach(ui) - register struct bus_device *ui; -{ - scsi_softc_t *sc = scsi_softc[ui->mi->unit]; - target_info_t *tgt = sc->target[(unsigned char)ui->slave]; - int i; - spl_t s; - - printf(" (%s %s) ", (*tgt->dev_ops->driver_name)(FALSE),tgt->tgt_name); - - if (tgt->flags & TGT_US) { - printf(" [this cpu]"); - return; - } - - s = spl0(); - - /* sense return from inquiry */ - scsi_request_sense(tgt, 0, 0); - - /* - * Do this twice, certain targets need it - */ - if (tgt->dev_ops != &scsi_devsw[SCSI_CPU]) { - (void) scsi_start_unit(tgt, SCSI_CMD_SS_START, 0); - i = 0; - while (scsi_start_unit(tgt, SCSI_CMD_SS_START, 0) == SCSI_RET_RETRY) { - if (i++ == 5) - printf(".. not yet online .."); - delay(1000000); - if (i == 60) { - printf(" seems hopeless."); - break; - } - } - } - - /* - * See if it is up and about - */ - scsi_test_unit_ready(tgt, 0); - - if (tgt->dev_ops->optimize != SCSI_OPTIMIZE_NULL) - (*tgt->dev_ops->optimize)(tgt); - - tgt->flags |= TGT_FULLY_PROBED; - - splx(s); -} - -/* - * Probe routine: - * See if a device answers. Used AFTER autoconf. - * - * Implementation: - * First ask the HBA to see if anyone is there at all, then - * call the scsi_slave and scsi_attach routines with a fake ui. - */ -boolean_t -scsi_probe( sc, tgt_ptr, target_id, ior) - scsi_softc_t *sc; - target_info_t **tgt_ptr; - int target_id; - io_req_t ior; -{ - struct bus_device ui; - target_info_t *tgt; - - if (!sc->probe || target_id > 7 || target_id == sc->initiator_id) - return FALSE; /* sanity */ - - if (sc->target[target_id] == 0) - scsi_slave_alloc( sc->masterno, target_id, sc->hw_state); - tgt = sc->target[target_id]; - tgt->flags = 0;/* we donno yet */ - tgt->dev_ops = 0; - - /* mildly enquire */ - if (!(sc->probe)(tgt, ior)) - goto fail; - - /* There is something there, see what it is */ - bzero(&ui, sizeof(ui)); - ui.ctlr = sc->masterno; - ui.unit = - ui.slave = target_id; - ui.name = ""; - - /* this fails on the name for sure */ - (void) scsi_slave( &ui, 0 /* brrrr */); - if ((tgt->flags & TGT_ALIVE) == 0) - goto fail; - - { - struct bus_ctlr mi; - - mi.unit = sc->masterno; - ui.mi = &mi; - printf("%s at slave %d ", - (*tgt->dev_ops->driver_name)(TRUE), target_id); - scsi_attach(&ui); - } - - *tgt_ptr = tgt; - return TRUE; -fail: - tgt->flags = 0; - return FALSE; -} - - -/* - * Watchdog routine: - * Issue a SCSI bus reset if a target holds up the - * bus for too long. - * - * Implementation: - * Each HBA that wants to use this should have a - * watchdog_t structure at the head of its hardware - * descriptor. This variable is set by this periodic - * routine and reset on bus activity. If it is not reset on - * time (say some ten seconds or so) we reset the - * SCSI bus. - * NOTE: - * An HBA must be ready to accept bus reset interrupts - * properly in order to use this. - */ -void scsi_watchdog(hw) - watchdog_t *hw; -{ - spl_t s = splbio(); - - switch (hw->watchdog_state) { - case SCSI_WD_EXPIRED: - - /* double check first */ - if (hw->nactive == 0) { - hw->watchdog_state = SCSI_WD_INACTIVE; - break; - } - if (scsi_debug) - printf("SCSI Watchdog expired\n"); - hw->watchdog_state = SCSI_WD_INACTIVE; - (*hw->reset)(hw); - break; - - case SCSI_WD_ACTIVE: - - hw->watchdog_state = SCSI_WD_EXPIRED; - break; - - case SCSI_WD_INACTIVE: - - break; - } - - /* do this here, fends against powered down devices */ - if (scsi_watchdog_period != 0) - timeout((int(*)())scsi_watchdog, (char*)hw, scsi_watchdog_period * hz); - - splx(s); -} - - -/* - * BusReset Notification: - * Called when the HBA sees a BusReset interrupt - * - * Implementation: - * Go through the list of targets, redo the synch - * negotiation, and restart whatever operation was - * in progress for that target. - */ -void scsi_bus_was_reset(sc) - scsi_softc_t *sc; -{ - register target_info_t *tgt; - int i; - /* - * Redo the synch negotiation - */ - for (i = 0; i < 8; i++) { - io_req_t ior; - spl_t s; - - if (i == sc->initiator_id) - continue; - tgt = sc->target[i]; - if (!tgt || !(tgt->flags & TGT_ALIVE)) - continue; - - tgt->flags &= ~(TGT_DID_SYNCH|TGT_DISCONNECTED); -#if 0 - /* the standard does *not* imply this gets reset too */ - tgt->sync_period = 0; - tgt->sync_offset = 0; -#endif - - /* - * retry the synch negotiation - */ - ior = tgt->ior; - tgt->ior = 0; - printf(".. tgt %d ", tgt->target_id); - if (BGET(scsi_no_synchronous_xfer,(unsigned char)sc->masterno,tgt->target_id)) - tgt->flags |= TGT_DID_SYNCH; - else { - s = spl0(); - scsi_test_unit_ready(tgt, 0); - splx(s); - } - tgt->ior = ior; - } - - /* - * Notify each target of the accident - */ - for (i = 0; i < 8; i++) { - if (i == sc->initiator_id) - continue; - tgt = sc->target[i]; - if (!tgt) - continue; - tgt->done = SCSI_RET_ABORTED|SCSI_RET_RETRY; - if (tgt->ior) - (*tgt->dev_ops->restart)( tgt, TRUE); - } - - printf("%s", " reset complete\n"); -} - -#endif NSCSI > 0 diff --git a/scsi/scsi.h b/scsi/scsi.h deleted file mode 100644 index 9aa0bee..0000000 --- a/scsi/scsi.h +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 9/90 - * - * Definitions of the SCSI-1 Standard - */ - -#ifndef _SCSI_SCSI_H_ -#define _SCSI_SCSI_H_ - -#include <nscsi.h> -#include <scsi/scsi_endian.h> - -/* - * Bus phases - */ - -#define SCSI_IO 0x01 /* Input/Output */ -#define SCSI_CD 0x02 /* Command/Data */ -#define SCSI_MSG 0x04 /* Message */ - -#define SCSI_PHASE_MASK 0x07 -#define SCSI_PHASE(x) ((x)&SCSI_PHASE_MASK) - -#define SCSI_PHASE_DATAO 0x00 /* 0 */ -#define SCSI_PHASE_DATAI SCSI_IO /* 1 */ -#define SCSI_PHASE_CMD SCSI_CD /* 2 */ -#define SCSI_PHASE_STATUS (SCSI_CD|SCSI_IO) /* 3 */ - /* 4..5 ANSI reserved */ -#define SCSI_PHASE_MSG_OUT (SCSI_MSG|SCSI_CD) /* 6 */ -#define SCSI_PHASE_MSG_IN (SCSI_MSG|SCSI_CD|SCSI_IO) /* 7 */ - -/* - * Single byte messages - * - * originator: I-nitiator T-arget - * T-support: M-andatory O-ptional - */ - -#define SCSI_COMMAND_COMPLETE 0x00 /* M T */ -#define SCSI_EXTENDED_MESSAGE 0x01 /* IT */ -#define SCSI_SAVE_DATA_POINTER 0x02 /* O T */ -#define SCSI_RESTORE_POINTERS 0x03 /* O T */ -#define SCSI_DISCONNECT 0x04 /* O T */ -#define SCSI_I_DETECTED_ERROR 0x05 /* M I */ -#define SCSI_ABORT 0x06 /* M I */ -#define SCSI_MESSAGE_REJECT 0x07 /* M IT */ -#define SCSI_NOP 0x08 /* M I */ -#define SCSI_MSG_PARITY_ERROR 0x09 /* M I */ -#define SCSI_LNKD_CMD_COMPLETE 0x0a /* O T */ -#define SCSI_LNKD_CMD_COMPLETE_F 0x0b /* O T */ -#define SCSI_BUS_DEVICE_RESET 0x0c /* M I */ - /* 0x0d..0x11 scsi2 */ - /* 0x12..0x1f reserved */ -#define SCSI_IDENTIFY 0x80 /* IT */ -# define SCSI_IFY_ENABLE_DISCONNECT 0x40 /* I */ -# define SCSI_IFY_LUNTAR 0x20 /* IT */ -# define SCSI_IFY_LUN_MASK 0x07 /* IT */ - - -/* Message codes 0x30..0x7f are reserved */ - -/* - * Extended messages, codes and formats - */ - -#define SCSI_MODIFY_DATA_PTR 0x00 /* T */ -typedef struct { - unsigned char xtn_msg_tag; /* const 0x01 */ - unsigned char xtn_msg_len; /* const 0x05 */ - unsigned char xtn_msg_code; /* const 0x00 */ - unsigned char xtn_msg_arg_1000; /* MSB, signed 2cmpl */ - unsigned char xtn_msg_arg_0200; - unsigned char xtn_msg_arg_0030; - unsigned char xtn_msg_arg_0004; /* LSB */ -} scsi_mod_ptr_t; - -#define SCSI_SYNC_XFER_REQUEST 0x01 /* IT */ -typedef struct { - unsigned char xtn_msg_tag; /* const 0x01 */ - unsigned char xtn_msg_len; /* const 0x03 */ - unsigned char xtn_msg_code; /* const 0x01 */ - unsigned char xtn_msg_xfer_period; /* times 4nsecs */ - unsigned char xtn_msg_xfer_offset; /* pending ack window */ -#define SCSI_SYNCH_XFER_OFFANY 0xff /* T unlimited */ -} scsi_synch_xfer_req_t; - -#define SCSI_XTN_IDENTIFY 0x02 /* IT -2 */ -typedef struct { - unsigned char xtn_msg_tag; /* const 0x01 */ - unsigned char xtn_msg_len; /* const 0x02 */ - unsigned char xtn_msg_code; /* const 0x02 */ - unsigned char xtn_msg_sublun; -} scsi_xtn_identify_t; - - /* 0x03..0x7f reserved */ - -#define SCSI_XTN_VENDOR_UQE 0x80 /* vendor unique bit */ -typedef struct { - unsigned char xtn_msg_tag; /* const 0x01 */ - unsigned char xtn_msg_len; /* args' len+1 (0-->256)*/ - unsigned char xtn_msg_code; /* const 0x80..0xff */ - unsigned char xtn_msg_args[1]; /* 0..255 bytes */ -} scsi_xtn_vedor_unique_t; - - -/* - * Commands, generic structures - */ - -/* SIX byte commands */ -typedef struct { - unsigned char scsi_cmd_code; /* group(7..5) and command(4..1) */ -#define SCSI_CODE_GROUP 0xe0 -#define SCSI_CODE_CMD 0x1f - unsigned char scsi_cmd_lun_and_lba1; /* lun(7..5) and block# msb[20..16] */ -#define SCSI_LUN_MASK 0xe0 -#define SCSI_LBA_MASK 0x1f -#define SCSI_LUN_SHIFT 5 - unsigned char scsi_cmd_lba2; /* block#[15.. 8] */ - unsigned char scsi_cmd_lba3; /* block#[ 7.. 0] */ - unsigned char scsi_cmd_xfer_len; /* if required */ - unsigned char scsi_cmd_ctrl_byte; /* contains: */ -#define SCSI_CTRL_VUQ 0xc0 /* vendor unique bits */ -#define SCSI_CTRL_RESVD 0x3c /* reserved, mbz */ -#define SCSI_CTRL_FLAG 0x02 /* send a complete_with_flag at end */ -#define SCSI_CTRL_LINK 0x01 /* link this command with next */ -} scsi_command_group_0; - -/* TEN byte commands */ -typedef struct { - unsigned char scsi_cmd_code; /* group(7..5) and command(4..1) */ - unsigned char scsi_cmd_lun_and_relbit;/* lun(7..5) and RelAdr(0) */ -#define SCSI_RELADR 0x01 - unsigned char scsi_cmd_lba1; /* block#[31..24] */ - unsigned char scsi_cmd_lba2; /* block#[23..16] */ - unsigned char scsi_cmd_lba3; /* block#[15.. 8] */ - unsigned char scsi_cmd_lba4; /* block#[ 7.. 0] */ - unsigned char scsi_cmd_xxx; /* reserved, mbz */ - unsigned char scsi_cmd_xfer_len_1; /* if required */ - unsigned char scsi_cmd_xfer_len_2; /* if required */ - unsigned char scsi_cmd_ctrl_byte; /* see above */ -} scsi_command_group_1, - scsi_command_group_2; - -/* TWELVE byte commands */ -typedef struct { - unsigned char scsi_cmd_code; /* group(7..5) and command(4..1) */ - unsigned char scsi_cmd_lun_and_relbit;/* lun(7..5) and RelAdr(0) */ - unsigned char scsi_cmd_lba1; /* block#[31..24] */ - unsigned char scsi_cmd_lba2; /* block#[23..16] */ - unsigned char scsi_cmd_lba3; /* block#[15.. 8] */ - unsigned char scsi_cmd_lba4; /* block#[ 7.. 0] */ - unsigned char scsi_cmd_xfer_len_1; /* if required */ - unsigned char scsi_cmd_xfer_len_2; /* if required */ - unsigned char scsi_cmd_xfer_len_3; /* if required */ - unsigned char scsi_cmd_xfer_len_4; /* if required */ - unsigned char scsi_cmd_xxx1; /* reserved, mbz */ - unsigned char scsi_cmd_ctrl_byte; /* see above */ -} scsi_command_group_5; - - -/* - * Commands, codes and aliases - */ - - /* GROUP 0 */ -#define SCSI_CMD_TEST_UNIT_READY 0x00 /* O all 2M all */ -#define scsi_cmd_test_unit_ready_t scsi_command_group_0 - -#define SCSI_CMD_REZERO_UNIT 0x01 /* O disk worm rom */ -#define SCSI_CMD_REWIND 0x01 /* M tape */ -#define scsi_cmd_rewind_t scsi_command_group_0 -#define scsi_cmd_rezero_t scsi_command_group_0 -# define SCSI_CMD_REW_IMMED 0x01 - - /* 0x02 vendor unique */ - -#define SCSI_CMD_REQUEST_SENSE 0x03 /* M all */ -#define scsi_cmd_request_sense_t scsi_command_group_0 -# define scsi_cmd_allocation_length scsi_cmd_xfer_len - -#define SCSI_CMD_FORMAT_UNIT 0x04 /* M disk O prin */ -#define scsi_cmd_format_t scsi_command_group_0 -# define SCSI_CMD_FMT_FMTDATA 0x10 -# define SCSI_CMD_FMT_CMPLIST 0x08 -# define SCSI_CMD_FMT_LIST_TYPE 0x07 -# define scsi_cmd_intleave1 scsi_cmd_lba3 -# define scsi_cmd_intleave2 scsi_cmd_xfer_len - -#define SCSI_CMD_READ_BLOCK_LIMITS 0x05 /* E tape */ -#define scsi_cmd_block_limits_t scsi_command_group_0 - - /* 0x06 vendor unique */ - -#define SCSI_CMD_REASSIGN_BLOCKS 0x07 /* O disk worm */ -#define scsi_cmd_reassign_blocks_t scsi_command_group_0 - -#define SCSI_CMD_READ 0x08 /* M disk tape O worm rom */ -#define SCSI_CMD_RECEIVE 0x08 /* O proc */ -#define SCSI_CMD_GET_MESSAGE 0x08 /* M comm */ -#define scsi_cmd_read_t scsi_command_group_0 -# define SCSI_CMD_TP_FIXED 0x01 /* tape */ -# define scsi_cmd_tp_len1 scsi_cmd_lba2 -# define scsi_cmd_tp_len2 scsi_cmd_lba3 -# define scsi_cmd_tp_len3 scsi_cmd_xfer_len - /* largest addressable blockno */ -#define SCSI_CMD_READ_MAX_LBA ((1 << 21) - 1) - - /* 0x09 vendor unique */ - -#define SCSI_CMD_WRITE 0x0a /* M disk tape O worm */ -#define SCSI_CMD_PRINT 0x0a /* M prin */ -#define SCSI_CMD_SEND 0x0a /* M proc */ -#define SCSI_CMD_SEND_MESSAGE 0x0a /* M comm */ -#define scsi_cmd_write_t scsi_command_group_0 - -#define SCSI_CMD_SEEK 0x0b /* O disk worm rom */ -#define SCSI_CMD_TRACK_SELECT 0x0b /* O tape */ -#define SCSI_CMD_SLEW_AND_PRINT 0x0b /* O prin */ -#define scsi_cmd_seek_t scsi_command_group_0 -# define SCSI_CMD_SLW_CHANNEL 0x01 -# define scsi_cmd_tp_trackno scsi_cmd_xfer_len -# define scsi_cmd_slew_value scsi_cmd_lba2 - - /* 0x0c..0x0e vendor unique */ - -#define SCSI_CMD_READ_REVERSE 0x0f /* O tape */ -#define scsi_cmd_rev_read_t scsi_command_group_0 - -#define SCSI_CMD_WRITE_FILEMARKS 0x10 /* M tape */ -#define SCSI_CMD_FLUSH_BUFFER 0x10 /* M prin */ -#define scsi_cmd_write_fil_t scsi_command_group_0 - -#define SCSI_CMD_SPACE 0x11 /* O tape */ -#define scsi_cmd_space_t scsi_command_group_0 -# define SCSI_CMD_SP_BLOCKS 0x00 -# define SCSI_CMD_SP_FIL 0x01 -# define SCSI_CMD_SP_SEQ_FIL 0x02 -# define SCSI_CMD_SP_EOT 0x03 - -#define SCSI_CMD_INQUIRY 0x12 /* E all (2M all) */ -#define scsi_cmd_inquiry_t scsi_command_group_0 -# define SCSI_CMD_INQ_EVPD 0x01 /* 2 */ -# define scsi_cmd_page_code scsi_cmd_lba2 /* 2 */ - -#define SCSI_CMD_VERIFY_0 0x13 /* O tape */ -#define scsi_cmd_verify_t scsi_command_group_0 -# define SCSI_CMD_VFY_BYTCMP 0x02 - -#define SCSI_CMD_RECOVER_BUFFERED_DATA 0x14 /* O tape prin */ -#define scsi_cmd_recover_buffer_t scsi_command_group_0 - -#define SCSI_CMD_MODE_SELECT 0x15 /* O disk tape prin worm rom */ -# define SCSI_CMD_MSL_PF 0x10 -# define SCSI_CMD_MSL_SP 0x01 -#define scsi_cmd_mode_select_t scsi_command_group_0 - -#define SCSI_CMD_RESERVE 0x16 /* O disk tape prin worm rom */ -#define scsi_cmd_reserve_t scsi_command_group_0 -# define SCSI_CMD_RES_3RDPTY 0x10 -# define SCSI_CMD_RES_3RDPTY_DEV 0x0e -# define SCSI_CMD_RES_EXTENT 0x01 -# define scsi_cmd_reserve_id scsi_cmd_lba2 -# define scsi_cmd_extent_llen1 scsi_cmd_lba3 -# define scsi_cmd_extent_llen2 scsi_cmd_xfer_len - -#define SCSI_CMD_RELEASE 0x17 /* O disk tape prin worm rom */ -#define scsi_cmd_release_t scsi_command_group_0 - -#define SCSI_CMD_COPY 0x18 /* O all */ -#define scsi_cmd_copy_t scsi_command_group_0 -# define SCSI_CMD_CPY_PAD 0x01 /* 2 */ -# define scsi_cmd_paraml_len0 scsi_cmd_lba2 -# define scsi_cmd_paraml_len1 scsi_cmd_lba3 -# define scsi_cmd_paraml_len2 scsi_cmd_xfer_len - -#define SCSI_CMD_ERASE 0x19 /* O tape */ -#define scsi_cmd_erase_t scsi_command_group_0 -# define SCSI_CMD_ER_LONG 0x01 - -#define SCSI_CMD_MODE_SENSE 0x1a /* O disk tape prin worm rom */ -#define scsi_cmd_mode_sense_t scsi_command_group_0 -# define scsi_cmd_ms_pagecode scsi_cmd_lba2 - -#define SCSI_CMD_START_STOP_UNIT 0x1b /* O disk prin worm rom */ -#define SCSI_CMD_LOAD_UNLOAD 0x1b /* O tape */ -#define scsi_cmd_start_t scsi_command_group_0 -# define SCSI_CMD_SS_IMMED 0x01 -# define scsi_cmd_ss_flags scsi_cmd_xfer_len -# define SCSI_CMD_SS_START 0x01 -# define SCSI_CMD_SS_RETEN 0x02 -# define SCSI_CMD_SS_RETAIN 0x01 -# define SCSI_CMD_SS_EJECT 0x02 - -#define SCSI_CMD_RECEIVE_DIAG_RESULTS 0x1c /* O all */ -#define scsi_cmd_receive_diag_t scsi_command_group_0 -# define scsi_cmd_allocation_length1 scsi_cmd_lba3 -# define scsi_cmd_allocation_length2 scsi_cmd_xfer_len - -#define SCSI_CMD_SEND_DIAGNOSTICS 0x1d /* O all */ -#define scsi_cmd_send_diag_t scsi_command_group_0 -# define SCSI_CMD_DIAG_SELFTEST 0x04 -# define SCSI_CMD_DIAG_DEVOFFL 0x02 -# define SCSI_CMD_DIAG_UNITOFFL 0x01 - -#define SCSI_CMD_PREVENT_ALLOW_REMOVAL 0x1e /* O disk tape worm rom */ -#define scsi_cmd_medium_removal_t scsi_command_group_0 -# define scsi_cmd_pa_prevent scsi_cmd_xfer_len /* 0x1 */ - - /* 0x1f reserved */ - - /* GROUP 1 */ - /* 0x20..0x24 vendor unique */ - -#define SCSI_CMD_READ_CAPACITY 0x25 /* E disk worm rom */ -#define scsi_cmd_read_capacity_t scsi_command_group_1 -# define scsi_cmd_rcap_flags scsi_cmd_xfer_len_2 -# define SCSI_CMD_RCAP_PMI 0x01 - - /* 0x26..0x27 vendor unique */ - -#define SCSI_CMD_LONG_READ 0x28 /* E disk M worm rom */ -#define scsi_cmd_long_read_t scsi_command_group_1 - - /* 0x29 vendor unique */ - -#define SCSI_CMD_LONG_WRITE 0x2a /* E disk M worm */ -#define scsi_cmd_long_write_t scsi_command_group_1 - -#define SCSI_CMD_LONG_SEEK 0x2b /* O disk worm rom */ -#define scsi_cmd_long_seek_t scsi_command_group_1 - - /* 0x2c..0x2d vendor unique */ - -#define SCSI_CMD_WRITE_AND_VERIFY 0x2e /* O disk worm */ -#define scsi_cmd_write_vfy_t scsi_command_group_1 -# define SCSI_CMD_VFY_BYTCHK 0x02 - -#define SCSI_CMD_VERIFY_1 0x2f /* O disk worm rom */ -#define scsi_cmd_verify_long_t scsi_command_group_1 -# define SCSI_CMD_VFY_BLKVFY 0x04 - -#define SCSI_CMD_SEARCH_HIGH 0x30 /* O disk worm rom */ -#define scsi_cmd_search_t scsi_command_group_1 -# define SCSI_CMD_SRCH_INVERT 0x10 -# define SCSI_CMD_SRCH_SPNDAT 0x02 - -#define SCSI_CMD_SEARCH_EQUAL 0x31 /* O disk worm rom */ -#define SCSI_CMD_SEARCH_LOW 0x32 /* O disk worm rom */ - -#define SCSI_CMD_SET_LIMITS 0x33 /* O disk worm rom */ -#define scsi_cmd_set_limits_t scsi_command_group_1 -# define SCSI_CMD_SL_RDINH 0x02 -# define SCSI_CMD_SL_WRINH 0x01 - - /* 0x34..0x38 reserved */ - -#define SCSI_CMD_COMPARE 0x39 /* O all */ -#define scsi_cmd_compare_t scsi_command_group_1 -# define scsi_cmd_1_paraml1 scsi_cmd_lba2 -# define scsi_cmd_1_paraml2 scsi_cmd_lba3 -# define scsi_cmd_1_paraml3 scsi_cmd_lba4 - -#define SCSI_CMD_COPY_AND_VERIFY 0x3a /* O all */ -#define scsi_cmd_copy_vfy_t scsi_command_group_1 -# define SCSI_CMD_CPY_BYTCHK 0x02 - - /* 0x3b..0x3f reserved */ - - /* GROUP 2 */ - /* 0x40..0x5f reserved */ - - /* GROUP 3 */ - /* 0x60..0x7f reserved */ - - /* GROUP 4 */ - /* 0x80..0x9f reserved */ - - /* GROUP 5 */ - /* 0xa0..0xaf vendor unique */ - /* 0xb0..0xbf reserved */ - - /* GROUP 6 */ - /* 0xc0..0xdf vendor unique */ - - /* GROUP 7 */ - /* 0xe0..0xff vendor unique */ - - -/* - * Command-specific results and definitions - */ - -/* inquiry data */ -typedef struct { - unsigned char periph_type; -#define SCSI_DISK 0x00 -#define SCSI_TAPE 0x01 -#define SCSI_PRINTER 0x02 -#define SCSI_CPU 0x03 -#define SCSI_WORM 0x04 -#define SCSI_CDROM 0x05 - - BITFIELD_2( unsigned char, - device_type : 7, - rmb : 1); - BITFIELD_3( unsigned char, - ansi : 3, - ecma : 3, - iso : 2); - unsigned char reserved; - unsigned char length; - unsigned char param[1]; -} scsi_inquiry_data_t; - -#define SCSI_INQ_STD_DATA -1 - -/* request sense data */ -#define SCSI_SNS_NOSENSE 0x0 -#define SCSI_SNS_RECOVERED 0x1 -#define SCSI_SNS_NOTREADY 0x2 -#define SCSI_SNS_MEDIUM_ERR 0x3 -#define SCSI_SNS_HW_ERR 0x4 -#define SCSI_SNS_ILLEGAL_REQ 0x5 -#define SCSI_SNS_UNIT_ATN 0x6 -#define SCSI_SNS_PROTECT 0x7 -#define SCSI_SNS_BLANK_CHK 0x8 -#define SCSI_SNS_VUQE 0x9 -#define SCSI_SNS_COPY_ABRT 0xa -#define SCSI_SNS_ABORTED 0xb -#define SCSI_SNS_EQUAL 0xc -#define SCSI_SNS_VOLUME_OVFL 0xd -#define SCSI_SNS_MISCOMPARE 0xe -#define SCSI_SNS_RESERVED 0xf - -typedef struct { - BITFIELD_3( unsigned char, - error_code : 4, - error_class : 3, - addr_valid : 1); -# define SCSI_SNS_XTENDED_SENSE_DATA 0x7 /* e.g. error_class=7 */ - union { - struct { - BITFIELD_2(unsigned char, - lba_msb : 5, - vuqe : 3); - unsigned char lba; - unsigned char lba_lsb; - } non_xtnded; - struct { - unsigned char segment_number; - BITFIELD_5(unsigned char, - sense_key : 4, - res : 1, - ili : 1, - eom : 1, - fm : 1); - unsigned char info0; - unsigned char info1; - unsigned char info2; - unsigned char info3; - unsigned char add_len; - unsigned char add_bytes[1];/* VARSIZE */ - } xtended; - } u; -} scsi_sense_data_t; - - -/* mode select params */ -typedef struct { - unsigned char reserved1; - unsigned char medium_type; - BITFIELD_3(unsigned char, - speed:4, /* special for tapes, reserved in SCSI-1 */ - buffer_mode:3, - reserved2:1); - unsigned char desc_len; - struct scsi_mode_parm_blockdesc { - unsigned char density_code; - unsigned char nblocks1; - unsigned char nblocks2; - unsigned char nblocks3; - unsigned char reserved; - unsigned char reclen1; - unsigned char reclen2; - unsigned char reclen3; - } descs[1]; /* VARSIZE, really */ -} scsi_mode_select_param_t; - -/* mode sense data (TAPE) */ -typedef struct { - unsigned char data_len; - unsigned char medium_type; - BITFIELD_3(unsigned char, - speed : 4, - buffered_mode : 3, - wp : 1); - unsigned char bdesc_len; - struct { - unsigned char density_code; - unsigned char no_blks_msb; - unsigned char no_blks; - unsigned char no_blks_lsb; - unsigned char reserved; - unsigned char blen_msb; - unsigned char blen; - unsigned char blen_lsb; - } bdesc[1]; /* VARSIZE */ - /* vuqe data might follow */ -} scsi_mode_sense_data_t; - -/* read capacity data */ -typedef struct { - unsigned char lba1; - unsigned char lba2; - unsigned char lba3; - unsigned char lba4; - unsigned char blen1; - unsigned char blen2; - unsigned char blen3; - unsigned char blen4; -} scsi_rcap_data_t; - -/* defect list(s) */ -typedef struct { - unsigned char res1; - unsigned char res2; - unsigned char list_len_msb; - unsigned char list_len_lsb; - struct { - unsigned char blockno_msb; - unsigned char blockno_sb1; - unsigned char blockno_sb2; - unsigned char blockno_lsb; - } defects[1]; /* VARSIZE */ -} scsi_Ldefect_data_t; - -/* block limits (tape) */ -typedef struct { - unsigned char res1; - unsigned char maxlen_msb; - unsigned char maxlen_sb; - unsigned char maxlen_lsb; - unsigned char minlen_msb; - unsigned char minlen_lsb; -} scsi_blimits_data_t; - -/* - * Status byte (a-la scsi1) - */ - -typedef union { - struct { - BITFIELD_4( unsigned char, - scsi_status_vendor_uqe1:1, - scsi_status_code:4, - scsi_status_vendor_uqe:2, - scsi_status_reserved:1); -# define SCSI_ST_GOOD 0x00 /* scsi_status_code values */ -# define SCSI_ST_CHECK_CONDITION 0x01 -# define SCSI_ST_CONDITION_MET 0x02 -# define SCSI_ST_BUSY 0x04 -# define SCSI_ST_INT_GOOD 0x08 -# define SCSI_ST_INT_MET 0x0a -# define SCSI_ST_RES_CONFLICT 0x0c - /* anything else is reserved */ - } st; - unsigned char bits; -} scsi_status_byte_t; - - -#endif _SCSI_SCSI_H_ diff --git a/scsi/scsi2.h b/scsi/scsi2.h deleted file mode 100644 index 93a5a76..0000000 --- a/scsi/scsi2.h +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi2.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 9/90 - * - * Additions and changes of the SCSI-II standard viz SCSI-I - */ - -#ifndef _SCSI_SCSI2_H_ -#define _SCSI_SCSI2_H_ - -#include <scsi/scsi_endian.h> - -/* - * Single byte messages - * - * originator: I-nitiator T-arget - * T-support: M-andatory O-ptional - */ - -#define SCSI_ABORT_TAG 0x0d /* O I 2 */ -#define SCSI_CLEAR_QUEUE 0x0e /* O I 2 */ -#define SCSI_INITIATE_RECOVERY 0x0f /* O IT2 */ -#define SCSI_RELEASE_RECOVERY 0x10 /* O I 2 */ -#define SCSI_TERMINATE_IO_PROCESS 0x11 /* O I 2 */ - -/* - * Two byte messages - */ -#define SCSI_SIMPLE_QUEUE_TAG 0x20 /* O IT2 */ -#define SCSI_HEADOF_QUEUE_TAG 0x21 /* O I 2 */ -#define SCSI_ORDERED_QUEUE_TAG 0x22 /* O I 2 */ -#define SCSI_IGNORE_WIDE_RESIDUE 0x23 /* O T2 */ - /* 0x24..0x2f reserved */ - -/* - * Extended messages, codes and formats - */ - -#define SCSI_WIDE_XFER_REQUEST 0x03 /* IT 2 */ -typedef struct { - unsigned char xtn_msg_tag; /* const 0x01 */ - unsigned char xtn_msg_len; /* const 0x02 */ - unsigned char xtn_msg_code; /* const 0x03 */ - unsigned char xtn_msg_xfer_width; -} scsi_wide_xfer_t; - -/* - * NOTE: some command-specific mods and extensions - * are actually defined in the scsi.h file for - * readability reasons - */ - - /* GROUP 1 */ - -#define SCSI_CMD_READ_DEFECT_DATA 0x37 /* O2 disk opti */ -typedef scsi_command_group_1 scsi_cmd_read_defect_t; -# define SCSI_CMD_RDD_LIST_TYPE 0x07 -# define SCSI_CMD_RDD_GLIST 0x08 -# define SCSI_CMD_RDD_PLIST 0x10 - -#define SCSI_CMD_WRITE_BUFFER 0x3b /* O2 all */ -typedef scsi_command_group_1 scsi_cmd_write_buffer_t; -# define SCSI_CMD_BUF_MODE 0x07 -# define scsi_cmd_buf_id scs_cmd_lba1 -# define scsi_cmd_buf_offset1 scs_cmd_lba2 -# define scsi_cmd_buf_offset2 scs_cmd_lba3 -# define scsi_cmd_buf_offset3 scs_cmd_lba4 -# define scsi_cmd_buf_alloc1 scs_cmd_xxx -# define scsi_cmd_buf_alloc2 scs_cmd_xfer_len_1 -# define scsi_cmd_buf_alloc3 scs_cmd_xfer_len_2 - -#define SCSI_CMD_READ_BUFFER 0x3c /* O2 all */ -#define scsi_cmd_read_buffer_t scsi_command_group_1 - - /* GROUP 2 */ - -#define SCSI_CMD_CHANGE_DEFINITION 0x40 /* O2 all */ -#define scsi_cmd_change_def_t scsi_command_group_2 -# define scsi_cmd_chg_save scsi_cmd_lba1 -# define scsi_cmd_chg_definition scsi_cmd_lba2 -# define SCSI_CMD_CHG_CURRENT 0x00 -# define SCSI_CMD_CHG_SCSI_1 0x01 -# define SCSI_CMD_CHG_CCS 0x02 -# define SCSI_CMD_CHG_SCSI_2 0x03 - - /* 0x41 reserved */ - -#define SCSI_CMD_READ_SUBCH 0x42 /* O2 rom */ -#define scsi_cmd_read_subch_t scsi_command_group_2 -# define SCSI_CMD_CD_MSF 0x02 -# define SCSI_CMD_RS_SUBQ 0x40 -# define scsi_cmd_rs_format scsi_cmd_lba2 -# define SCSI_CMD_RS_FMT_SUBQ 0x00 -# define SCSI_CMD_RS_FMT_CURPOS 0x01 -# define SCSI_CMD_RS_FMT_CATALOG 0x02 -# define SCSI_CMD_RS_FMT_ISRC 0x03 -# define scsi_cmd_rs_trackno scsi_cmd_xxx - - -#define SCSI_CMD_READ_TOC 0x43 /* O2 rom */ -#define scsi_cmd_read_toc_t scsi_command_group_2 -# define scsi_cmd_rtoc_startT scsi_cmd_xxx - -#define SCSI_CMD_READ_HEADER 0x44 /* O2 rom */ -#define scsi_cmd_read_header_t scsi_command_group_2 - -#define SCSI_CMD_PLAY_AUDIO 0x45 /* O2 rom */ -#define scsi_cmd_play_audio_t scsi_command_group_2 - -#define SCSI_CMD_PLAY_AUDIO_MSF 0x47 /* O2 rom */ -#define scsi_cmd_play_audio_msf_t scsi_command_group_2 -# define scsi_cmd_pamsf_startM scsi_cmd_lba2 -# define scsi_cmd_pamsf_startS scsi_cmd_lba3 -# define scsi_cmd_pamsf_startF scsi_cmd_lba4 -# define scsi_cmd_pamsf_endM scsi_cmd_xxx -# define scsi_cmd_pamsf_endS scsi_cmd_xfer_len_1 -# define scsi_cmd_pamsf_endF scsi_cmd_xfer_len_2 - -#define SCSI_CMD_PLAY_AUDIO_TI 0x48 /* O2 rom */ -#define scsi_cmd_play_audio_ti_t scsi_command_group_2 -# define scsi_cmd_pati_startT scsi_cmd_lba3 -# define scsi_cmd_pati_startI scsi_cmd_lba4 -# define scsi_cmd_pati_endT scsi_cmd_xfer_len_1 -# define scsi_cmd_pati_endI scsi_cmd_xfer_len_2 - -#define SCSI_CMD_PLAY_AUDIO_TR 0x49 /* O2 rom */ -#define scsi_cmd_play_audio_tr_t scsi_command_group_2 -# define scsi_cmd_patr_startT scsi_cmd_xxx - - -#define SCSI_CMD_PAUSE_RESUME 0x4b /* O2 rom */ -#define scsi_cmd_pausres_t scsi_command_group_2 -# define SCSI_CMD_PAUSRES_RESUME 0x01 -# define scsi_cmd_pausres_res scsi_cmd_xfer_len_2 - -#define SCSI_CMD_LOG_SELECT 0x4c /* O2 all */ -#define scsi_cmd_logsel_t scsi_command_group_2 -# define SCSI_CMD_LOG_SP 0x01 -# define SCSI_CMD_LOG_PCR 0x02 -# define scsi_cmd_log_page_control scsi_cmd_lba1 - -#define SCSI_CMD_LOG_SENSE 0x4d /* O2 all */ -#define scsi_cmd_logsense_t scsi_command_group_2 -# define SCSI_CMD_LOG_PPC 0x02 -# define scsi_cmd_log_page_code scsi_cmd_lba1 -# define scsi_cmd_log_param_ptr1 scsi_cmd_lba4 -# define scsi_cmd_log_param_ptr2 scsi_cmd_xxx - - - /* 0x4e..0x54 reserved */ - -#define SCSI_CMD_MODE_SELECT_2 0x55 /* Z2 */ -#define scsi_cmd_mode_select_long_t scsi_command_group_2 -# define SCSI_CMD_MSL2_PF 0x10 -# define SCSI_CMD_MSL2_SP 0x01 - - /* 0x56..0x59 reserved */ - -#define SCSI_CMD_MODE_SENSE_2 0x5a /* Z2 */ -#define scsi_cmd_mode_sense_long_t scsi_command_group_2 -# define SCSI_CMD_MSS2_DBD 0x08 - - /* 0x5b..0x5f reserved */ - - /* GROUP 5 */ - -#define SCSI_CMD_PLAY_AUDIO_LONG 0xa5 /* O2 rom */ -#define scsi_cmd_play_audio_l_t scsi_command_group_5 - -#define SCSI_CMD_PLAY_AUDIO_TR_LONG 0xa9 /* O2 rom */ -#define scsi_cmd_play_audio_tr_l_t scsi_command_group_5 -# define scsi_cmd_patrl_startT scsi_cmd_xxx1 - - -/* - * Command specific defines - */ -typedef struct { - BITFIELD_2(unsigned char, - periph_type : 5, - periph_qual : 3); -#define SCSI_SCANNER 0x06 /* periph_type values */ -#define SCSI_MEMORY 0x07 -#define SCSI_J_BOX 0x08 -#define SCSI_COMM 0x09 -#define SCSI_PREPRESS1 0x0a -#define SCSI_PREPRESS2 0x0b - -#define SCSI_PERIPH_CONNECTED 0x00 /* periph_qual values */ -#define SCSI_PERIPH_DISCONN 0x20 -#define SCSI_PERIPH_NOTHERE 0x30 - - BITFIELD_2(unsigned char, - device_type : 7, - rmb : 1); - - BITFIELD_3( unsigned char, - ansi : 3, - ecma : 3, - iso : 2); - - BITFIELD_4( unsigned char, - response_fmt : 4, - res1 : 2, - trmIOP : 1, - aenc : 1); - unsigned char length; - unsigned char res2; - unsigned char res3; - - BITFIELD_8(unsigned char, - SftRe : 1, - CmdQue : 1, - res4 : 1, - Linked : 1, - Sync : 1, - Wbus16 : 1, - Wbus32 : 1, - RelAdr : 1); - - unsigned char vendor_id[8]; - unsigned char product_id[16]; - unsigned char product_rev[4]; - unsigned char vendor_uqe[20]; - unsigned char reserved[40]; - unsigned char vendor_uqe1[1]; /* varsize */ -} scsi2_inquiry_data_t; -#define SCSI_INQ_SUPP_PAGES 0x00 -#define SCSI_INQ_A_INFO 0x01 /* 0x01..0x1f, really */ -#define SCSI_INQ_SERIALNO 0x80 -#define SCSI_INQ_IMPL_OPDEF 0x81 -#define SCSI_INQ_A_IMPL_OPDEF 0x82 - -/* mode_select */ -typedef struct { - unsigned char data_len; - unsigned char medium_type; - unsigned char device_specific; - unsigned char desc_len; - /* block descriptors are optional, same struct as scsi1 */ - /* page info then follows, see individual pages */ -} scsi2_mode_param_t; - -/* - * CDROM thingies - */ -typedef union { - struct { - unsigned char xxx; - unsigned char minute; - unsigned char second; - unsigned char frame; - } msf; - struct { - unsigned char lba1; - unsigned char lba2; - unsigned char lba3; - unsigned char lba4; - } lba; -} cdrom_addr_t; - -typedef struct { - unsigned char len1; /* MSB */ - unsigned char len2; /* LSB */ - unsigned char first_track; - unsigned char last_track; - struct cdrom_toc_desc { - - unsigned char xxx; - - BITFIELD_2(unsigned char, - control : 4, - adr : 4); - - unsigned char trackno; - unsigned char xxx1; - cdrom_addr_t absolute_address; - } descs[1]; /* varsize */ -} cdrom_toc_t; - -typedef struct { - unsigned char xxx; - - unsigned char audio_status; -#define SCSI_CDST_INVALID 0x00 -#define SCSI_CDST_PLAYING 0x11 -#define SCSI_CDST_PAUSED 0x12 -#define SCSI_CDST_COMPLETED 0x13 -#define SCSI_CDST_ERROR 0x14 -#define SCSI_CDST_NO_STATUS 0x15 - - unsigned char len1; - unsigned char len2; - struct cdrom_chanQ { - unsigned char format; - BITFIELD_2(unsigned char, - control : 4, - adr : 4); - unsigned char trackno; - unsigned char indexno; - cdrom_addr_t absolute_address; - cdrom_addr_t relative_address; - BITFIELD_2(unsigned char, - xxx : 7, - mcv : 1); - unsigned char catalog[15]; - BITFIELD_2(unsigned char, - xxx1 : 7, - tcv : 1); - unsigned char isrc[15]; - } subQ; -} cdrom_chan_data_t; - -/* subsets */ -typedef struct { - unsigned char xxx; - unsigned char audio_status; - unsigned char len1; - unsigned char len2; - struct { - unsigned char format; - BITFIELD_2(unsigned char, - control : 4, - adr : 4); - unsigned char trackno; - unsigned char indexno; - cdrom_addr_t absolute_address; - cdrom_addr_t relative_address; - } subQ; -} cdrom_chan_curpos_t; - -typedef struct { - unsigned char xxx; - unsigned char audio_status; - unsigned char len1; - unsigned char len2; - struct { - unsigned char format; - unsigned char xxx1[3]; - BITFIELD_2(unsigned char, - xxx : 7, - mcv : 1); - unsigned char catalog[15]; - } subQ; -} cdrom_chan_catalog_t; - -typedef struct { - unsigned char xxx; - unsigned char audio_status; - unsigned char len1; - unsigned char len2; - struct { - unsigned char format; - BITFIELD_2(unsigned char, - control : 4, - adr : 4); - unsigned char trackno; - unsigned char xxx0; - BITFIELD_2(unsigned char, - xxx1 : 7, - tcv : 1); - unsigned char isrc[15]; - } subQ; -} cdrom_chan_isrc_t; - -/* Audio page */ -typedef struct { - scsi_mode_sense_data_t h; /* includes bdescs */ - unsigned char page_code; -#define SCSI_CD_AUDIO_PAGE 0x0e - unsigned char page_len; - BITFIELD_4(unsigned char, - xxx1 : 1, - sotc : 1, - imm : 1, - xxx2 : 5); - unsigned char xxx3[2]; - BITFIELD_3(unsigned char, - fmt : 4, - xxx4 : 3, - aprv : 1); - unsigned char bps1; - unsigned char bps2; - BITFIELD_2(unsigned char, - sel0 : 4, - xxx5 : 4); - unsigned char vol0; - BITFIELD_2(unsigned char, - sel1 : 4, - xxx6 : 4); - unsigned char vol1; - BITFIELD_2(unsigned char, - sel2 : 4, - xxx7 : 4); - unsigned char vol2; - BITFIELD_2(unsigned char, - sel3 : 4, - xxx8 : 4); - unsigned char vol3; -} cdrom_audio_page_t; - -/* - * Status byte (a-la scsi2) - */ - -typedef union { - struct { - BITFIELD_3( unsigned char, - scsi_status_reserved1:1, - scsi_status_code:5, - scsi_status_reserved2:2); - /* more scsi_status_code values */ - /* 00..0c as in SCSI-I */ -# define SCSI_ST2_CMD_TERMINATED 0x11 /* 2 */ -# define SCSI_ST2_QUEUE_FULL 0x14 /* 2 */ - /* anything else is reserved */ - } st; - unsigned char bits; -} scsi2_status_byte_t; - -#endif _SCSI_SCSI2_H_ diff --git a/scsi/scsi_alldevs.c b/scsi/scsi_alldevs.c deleted file mode 100644 index 2c4f37e..0000000 --- a/scsi/scsi_alldevs.c +++ /dev/null @@ -1,858 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_alldevs.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Middle layer of the SCSI driver: SCSI protocol implementation - * This file contains code for SCSI commands defined for all device types. - */ - -#include <mach/std_types.h> -#include <sys/types.h> -#include <scsi/compat_30.h> - -#include <scsi/scsi.h> -#include <scsi/scsi2.h> -#include <scsi/scsi_defs.h> - -#if (NSCSI > 0) - -void scsi_print_add_sense_keys(); /* forward */ - -/* - * Utilities - */ -void scsi_go_and_wait(tgt, insize, outsize, ior) - target_info_t *tgt; - int insize, outsize; - io_req_t ior; -{ - register scsi_softc_t *sc = scsi_softc[(unsigned char)tgt->masterno]; - - tgt->ior = ior; - - (*sc->go)(tgt, insize, outsize, ior==0); - - if (ior) - iowait(ior); - else - while (tgt->done == SCSI_RET_IN_PROGRESS); -} - -void scsi_go(tgt, insize, outsize, cmd_only) - target_info_t *tgt; - int insize, outsize, cmd_only; -{ - register scsi_softc_t *sc = scsi_softc[(unsigned char)tgt->masterno]; - - (*sc->go)(tgt, insize, outsize, cmd_only); -} - -int sizeof_scsi_command( - unsigned char cmd) -{ - switch ((cmd & SCSI_CODE_GROUP) >> 5) { - case 0: return sizeof(scsi_command_group_0); - case 1: return sizeof(scsi_command_group_1); - case 2: return sizeof(scsi_command_group_2); - /* 3,4 reserved */ - case 5: return sizeof(scsi_command_group_5); - /* 6,7 vendor specific (!!) */ - case 6: return sizeof(scsi_command_group_2); - } -} - -/* - * INQUIRY (Almost mandatory) - */ -int scsi_inquiry( tgt, pagecode) - register target_info_t *tgt; - int pagecode; -{ - scsi_cmd_inquiry_t *cmd; - boolean_t no_ify = TRUE; - -retry: - cmd = (scsi_cmd_inquiry_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_INQUIRY; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_xfer_len = 0xff; /* max len always */ - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ -/*#ifdef SCSI2*/ - if (pagecode != SCSI_INQ_STD_DATA) { - cmd->scsi_cmd_lun_and_lba1 |= SCSI_CMD_INQ_EVPD; - cmd->scsi_cmd_page_code = pagecode; - } else -/*#endif SCSI2*/ - cmd->scsi_cmd_page_code = 0; - - tgt->cur_cmd = SCSI_CMD_INQUIRY; - - /* - * Note: this is sent when we do not know much about the - * target, so we might not put an identify message upfront - */ - scsi_go(tgt, sizeof(*cmd), 0xff, no_ify); - - /* - * This spin loop is because we are called at autoconf - * time where we cannot thread_block(). Sigh. - */ - while (tgt->done == SCSI_RET_IN_PROGRESS) ; - if (tgt->done == SCSI_RET_RETRY) /* sync negotiation ? */ - goto retry; - if ((tgt->done != SCSI_RET_SUCCESS) && no_ify) { - no_ify = FALSE; - goto retry; - } - return tgt->done; -} - -void scsi_print_inquiry( inq, pagecode, result) - scsi2_inquiry_data_t *inq; - int pagecode; - char *result; -{ - static char *periph_names[10] = { - "disk", "tape", "printer", "processor", "WORM-disk", - "CD-ROM", "scanner", "memory", "jukebox", "communication" - }; - static char *periph_state[4] = { - "online", "offline", "?", "absent" - }; - - char dev[SCSI_TARGET_NAME_LEN], *devname; - register int i, j = 0; - - if (pagecode != SCSI_INQ_STD_DATA) - return; - - devname = result ? result : dev; - - if (!result) { - printf("\n\t%s%s %s (%s %x)", - (inq->rmb) ? "" : "non-", "removable SCSI", - (inq->periph_type > 10) ? - "?device?" : periph_names[inq->periph_type], - periph_state[inq->periph_qual & 0x3], - inq->device_type); - printf("\n\t%s%s%s", - inq->iso ? "ISO-compliant, " : "", - inq->ecma ? "ECMA-compliant, " : "", - inq->ansi ? "ANSI-compliant, " : ""); - if (inq->ansi) - printf("%s%d, ", "SCSI-", inq->ansi); - if (inq->response_fmt == 2) - printf("%s%s%s%s%s%s%s%s%s%s%s", "Supports: ", - inq->aenc ? "AENC, " : "", - inq->trmIOP ? "TrmIOP, " : "", - inq->RelAdr ? "RelAdr, " : "", - inq->Wbus32 ? "32 bit xfers, " : "", - inq->Wbus16 ? "16 bis xfers, " : "", - inq->Sync ? "Sync xfers, " : "", - inq->Linked ? "Linked cmds, " : "", - inq->CmdQue ? "Tagged cmd queues, " : "", - inq->SftRe ? "Soft" : "Hard", " RESET, "); - } - - for (i = 0; i < 8; i++) - if (inq->vendor_id[i] != ' ') - devname[j++] = inq->vendor_id[i]; - devname[j++] = ' '; - for (i = 0; i < 16; i++) - if (inq->product_id[i] != ' ') - devname[j++] = inq->product_id[i]; - devname[j++] = ' '; - for (i = 0; i < 4; i++) - if (inq->product_rev[i] != ' ') - devname[j++] = inq->product_rev[i]; -#if unsafe - devname[j++] = ' '; - for (i = 0; i < 8; i++) - if (inq->vendor_uqe[i] != ' ') - devname[j++] = inq->vendor_uqe[i]; -#endif - devname[j] = 0; - - if (!result) - printf("(%s, %s%s)\n", devname, "SCSI ", - (inq->periph_type > 10) ? - "?device?" : periph_names[inq->periph_type]); -} - -/* - * REQUESTE SENSE (Mandatory, All) - */ - -int scsi_request_sense(tgt, ior, data) - register target_info_t *tgt; - io_req_t ior; - char **data; -{ - scsi_cmd_request_sense_t *cmd; - - cmd = (scsi_cmd_request_sense_t *) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_REQUEST_SENSE; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_allocation_length = 0xff; /* max len always */ - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_REQUEST_SENSE; - - if (ior==0) - scsi_go_and_wait (tgt, sizeof(*cmd), 0xff, ior); - else { - scsi_go(tgt, sizeof(*cmd), 0xff, FALSE); - return tgt->done; - } - - if (data) - *data = tgt->cmd_ptr; - - (void) scsi_check_sense_data(tgt, tgt->cmd_ptr); - - return tgt->done; -} - -boolean_t -scsi_check_sense_data(tgt, sns) - register target_info_t *tgt; - scsi_sense_data_t *sns; -{ - unsigned char code; - - if (sns->error_class != SCSI_SNS_XTENDED_SENSE_DATA) { - printf("Bad sense data, vuqe class x%x code x%x\n", - sns->error_class, sns->error_code); - return FALSE; /* and good luck */ - } else { - code = sns->u.xtended.sense_key; - - switch (code) { - case SCSI_SNS_NOSENSE: - case SCSI_SNS_EQUAL: - return TRUE; - break; - case SCSI_SNS_RECOVERED: - scsi_error(tgt, SCSI_ERR_BAD | SCSI_ERR_SENSE, - code, sns->u.xtended.add_bytes); - return TRUE; - break; - case SCSI_SNS_UNIT_ATN: - scsi_error(tgt, SCSI_ERR_SENSE, - code, sns->u.xtended.add_bytes); - return TRUE; - break; - case SCSI_SNS_NOTREADY: - tgt->done = SCSI_RET_RETRY; - return TRUE; - case SCSI_SNS_ILLEGAL_REQ: - if (tgt->flags & TGT_OPTIONAL_CMD) - return TRUE; - /* fall through */ - default: -/* e.g. - case SCSI_SNS_MEDIUM_ERR: - case SCSI_SNS_HW_ERR: - case SCSI_SNS_PROTECT: - case SCSI_SNS_BLANK_CHK: - case SCSI_SNS_VUQE: - case SCSI_SNS_COPY_ABRT: - case SCSI_SNS_ABORTED: - case SCSI_SNS_VOLUME_OVFL: - case SCSI_SNS_MISCOMPARE: - case SCSI_SNS_RESERVED: -*/ - scsi_error(tgt, SCSI_ERR_GRAVE|SCSI_ERR_SENSE, - code, sns->u.xtended.add_bytes); - return FALSE; - break; - } - } -} - -/* - * START STOP UNIT (Optional, disk prin work rom tape[load/unload]) - */ -int scsi_start_unit( tgt, ss, ior) - register target_info_t *tgt; - int ss; - io_req_t ior; -{ - scsi_cmd_start_t *cmd; - - cmd = (scsi_cmd_start_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_START_STOP_UNIT; - cmd->scsi_cmd_lun_and_lba1 = SCSI_CMD_SS_IMMED;/* 0 won't work ? */ - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_ss_flags = ss; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_START_STOP_UNIT; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - return tgt->done; -} - -/* - * TEST UNIT READY (Optional, All) - * Note: this is where we do the synch negotiation at autoconf - */ -int scsi_test_unit_ready( tgt, ior) - register target_info_t *tgt; - io_req_t ior; -{ - scsi_cmd_test_unit_ready_t *cmd; - - cmd = (scsi_cmd_test_unit_ready_t*) (tgt->cmd_ptr); - - cmd->scsi_cmd_code = SCSI_CMD_TEST_UNIT_READY; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_ss_flags = 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_TEST_UNIT_READY; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - - return tgt->done; -} - -/* - * RECEIVE DIAGNOSTIC RESULTS (Optional, All) - */ -int scsi_receive_diag( tgt, result, result_len, ior) - register target_info_t *tgt; - char *result; - int result_len; - io_req_t ior; -{ - scsi_cmd_receive_diag_t *cmd; - - cmd = (scsi_cmd_receive_diag_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_RECEIVE_DIAG_RESULTS; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = result_len >> 8 & 0xff; - cmd->scsi_cmd_xfer_len = result_len & 0xff; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_RECEIVE_DIAG_RESULTS; - - scsi_go_and_wait(tgt, sizeof(*cmd), result_len, ior); - - bcopy(tgt->cmd_ptr, (char*)result, result_len); - - return tgt->done; -} - - -int scsi_mode_sense( tgt, pagecode, len, ior) - register target_info_t *tgt; - int pagecode; - int len; - io_req_t ior; -{ - scsi_cmd_mode_sense_t *cmd; - - cmd = (scsi_cmd_mode_sense_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_MODE_SENSE; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_ms_pagecode = pagecode; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_xfer_len = len; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_MODE_SENSE; - - scsi_go_and_wait(tgt, sizeof(*cmd), len, ior); - - return tgt->done; -} - -#if 0 /* unused */ - -/* - * COPY (Optional, All) - */ -void scsi_copy( tgt, params, params_len, ior) - register target_info_t *tgt; - char *params; - io_req_t ior; -{ - scsi_cmd_copy_t *cmd; - - cmd = (scsi_cmd_copy_t*) (tgt->cmd_ptr; - cmd->scsi_cmd_code = SCSI_CMD_COPY; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba2 = params_len>>16 & 0xff; - cmd->scsi_cmd_lba3 = params_len >> 8 & 0xff; - cmd->scsi_cmd_xfer_len = params_len & 0xff; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - bcopy(params, cmd + 1, params_len); - - tgt->cur_cmd = SCSI_CMD_COPY; - - scsi_go_and_wait(tgt, sizeof(*cmd) + params_len, 0, ior); -} - -/* - * SEND DIAGNOSTIC (Optional, All) - */ -void scsi_send_diag( tgt, flags, params, params_len, ior) - register target_info_t *tgt; - char *params; - io_req_t ior; -{ - scsi_cmd_send_diag_t *cmd; - - cmd = (scsi_cmd_send_diag_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_SEND_DIAGNOSTICS; - cmd->scsi_cmd_lun_and_lba1 = flags & 0x7; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = params_len >> 8 & 0xff; - cmd->scsi_cmd_xfer_len = params_len & 0xff; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - bcopy(params, cmd + 1, params_len); - - tgt->cur_cmd = SCSI_CMD_SEND_DIAGNOSTICS; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); -} - -/* - * COMPARE (Optional, All) - */ -void scsi_compare( tgt, params, params_len, ior) - register target_info_t *tgt; - char *params; - io_req_t ior; -{ - scsi_cmd_compare_t *cmd; - - cmd = (scsi_cmd_compare_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_COMPARE; - cmd->scsi_cmd_lun_and_relbit = 0; - cmd->scsi_cmd_lba1 = 0; - cmd->scsi_cmd_1_paraml1 = params_len >> 16 & 0xff; - cmd->scsi_cmd_1_paraml2 = params_len >> 8 & 0xff; - cmd->scsi_cmd_1_paraml3 = params_len & 0xff; - cmd->scsi_cmd_xxx = 0; - cmd->scsi_cmd_xfer_len_1 = 0; - cmd->scsi_cmd_xfer_len_2 = 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - bcopy(params, cmd + 1, params_len); - - tgt->cur_cmd = SCSI_CMD_COMPARE; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); -} - -/* - * COPY AND VERIFY (Optional, All) - */ -void scsi_copy_and_verify( tgt, params, params_len, bytchk, ior) - register target_info_t *tgt; - char *params; - io_req_t ior; -{ - scsi_cmd_compare_t *cmd; - - cmd = (scsi_cmd_compare_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_COMPARE; - cmd->scsi_cmd_lun_and_relbit = bytchk ? SCSI_CMD_CPY_BYTCHK : 0; - cmd->scsi_cmd_lba1 = 0; - cmd->scsi_cmd_1_paraml1 = params_len >> 16 & 0xff; - cmd->scsi_cmd_1_paraml2 = params_len >> 8 & 0xff; - cmd->scsi_cmd_1_paraml3 = params_len & 0xff; - cmd->scsi_cmd_xxx = 0; - cmd->scsi_cmd_xfer_len_1 = 0; - cmd->scsi_cmd_xfer_len_2 = 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - bcopy(params, cmd + 1, params_len); - - tgt->cur_cmd = SCSI_CMD_COMPARE; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); -} - -#endif - -#ifdef SCSI2 -scsi_change_definition -scsi_log_select -scsi_log_sense -scsi_long_mode_select -scsi_read_buffer -scsi_write_buffer -#endif SCSI2 - -/* - * Warn user of some device error - */ -int scsi_debug = 0; - -static char *sns_msg[SCSI_SNS_RESERVED+1] = { - "No Sense Data",/* shouldn't happen */ - "Recovered", - "Unit not ready", - "Medium", - "Hardware failure", - "Illegal request", - "Unit Attention Condition", - "Protection", - "Blank Check", - "Vendor Unique", - "Copy Operation Aborted", - "Aborted Command", - "Equal Comparison", - "Volume Overflow", - "Miscompare", - "Reserved" -}; - -void -scsi_error( tgt, code, info, addtl) - target_info_t *tgt; - unsigned code; - unsigned info; - char *addtl; -{ - char unit; - char *msg, *cmd; - scsi2_status_byte_t status; - if (scsi_debug) - code |= SCSI_ERR_GRAVE; - - if (tgt) - unit = tgt->unit_no + '0'; - else - unit = '?'; - - - switch (SCSI_ERR_CLASS(code)) { - case SCSI_ERR_STATUS: - cmd = "Bad status return"; - status.bits = info; - switch (status.st.scsi_status_code) { - case SCSI_ST_GOOD: - case SCSI_ST_CONDITION_MET: - case SCSI_ST_INT_GOOD: - case SCSI_ST_INT_MET: - return; /* all is fine */ - case SCSI_ST_CHECK_CONDITION: - msg = "Check condition"; break; - case SCSI_ST_RES_CONFLICT: - msg = "Reservation conflict"; break; - case SCSI_ST_BUSY: - msg = "Target busy"; break; - case SCSI_ST2_QUEUE_FULL: - msg = "Queue full"; break; - case SCSI_ST2_CMD_TERMINATED: - msg = "Command terminated"; break; - default: - msg = "Strange"; break; - } - break; - case SCSI_ERR_SENSE: - cmd = "Sensed a"; - msg = sns_msg[info & 0xf]; - break; - case SCSI_ERR_MSEL: - cmd = "Mode select broken"; msg = ""; break; - default: - cmd = "Generic"; msg = ""; - } - if (SCSI_ERR_GRAVITY(code)) { - printf("\n%s%c: %s %s %sx%x", "target ", unit, cmd, msg, - "error, code ", info); - if (addtl) { - unsigned int add[3]; - bcopy(addtl, (char*)add, 3*sizeof(int)); - printf("%s x%x x%x x%x", ", additional info ", - add[0], add[1], add[2]); - } - printf("\n"); - } -} - -void scsi_print_sense_data(sns) - scsi_sense_data_t *sns; -{ - printf("Sense data: %s%s, segment %d", - sns_msg[sns->u.xtended.sense_key], " error", - sns->u.xtended.segment_number); - if (sns->u.xtended.ili) printf(", IncorrectLengthIndicator"); - if (sns->u.xtended.eom) printf(", EndOfMedium"); - if (sns->u.xtended.fm) printf(", FileMark"); - - if (sns->addr_valid) { - unsigned int info; - info = (sns->u.xtended.info0 << 24) | - (sns->u.xtended.info1 << 16) | - (sns->u.xtended.info2 << 8) | - sns->u.xtended.info3; - printf(", Info x%x", info); - } - - if (sns->u.xtended.add_len > 6) - scsi_print_add_sense_keys(sns->u.xtended.add_bytes[4], - sns->u.xtended.add_bytes[5]); -} - -/* - * Table of the official SCSI-2 error messages - * Last update: - * X3T9.2/86-109, Revision 10c, March 9, 1990 - */ -static struct addtl_sns_keys_msg { - unsigned char byte12; - unsigned char byte13; - char *means; -} addtl_sns_msgs[] = { - { 0x00, 0x00, "No additional sense information" }, - { 0x00, 0x01, "Filemark detected" }, - { 0x00, 0x02, "End-of-partition/medium detected" }, - { 0x00, 0x03, "Setmark detected" }, - { 0x00, 0x04, "Beginning of partition/medium detected" }, - { 0x00, 0x05, "End-of-data detected" }, - { 0x00, 0x06, "I/O process terminated" }, - { 0x00, 0x11, "Audio play operation in progress" }, - { 0x00, 0x12, "Audio play operation paused" }, - { 0x00, 0x13, "Audio play operation successfully completed" }, - { 0x00, 0x14, "Audio play operation stopped due to error" }, - { 0x00, 0x15, "No current audio status to return" }, - { 0x01, 0x00, "No index/sector signal" }, - { 0x02, 0x00, "No seek complete" }, - { 0x03, 0x00, "Peripheral device write fault" }, - { 0x03, 0x01, "No write current" }, - { 0x03, 0x02, "Excessive write errors" }, - { 0x04, 0x00, "Logical unit not ready, cause not reportable" }, - { 0x04, 0x01, "Logical unit is in process of becoming ready" }, - { 0x04, 0x02, "Logical unit not ready, initializing command required" }, - { 0x04, 0x03, "Logical unit not ready, manual intervention required" }, - { 0x04, 0x04, "Logical unit not ready, format in progress" }, - { 0x05, 0x00, "Logical unit does not respond to selection" }, - { 0x06, 0x00, "No reference position found" }, - { 0x07, 0x00, "Multiple peripheral devices selected" }, - { 0x08, 0x00, "Logical unit communication failure" }, - { 0x08, 0x01, "Logical unit communication time-out" }, - { 0x08, 0x02, "Logical unit communication parity error" }, - { 0x09, 0x00, "Track following error" }, - { 0x09, 0x01, "Tracking servo failure" }, - { 0x09, 0x02, "Focus servo failure" }, - { 0x09, 0x03, "Spindle servo failure" }, - { 0x0a, 0x00, "Error log overflow" }, - { 0x0c, 0x00, "Write error" }, - { 0x0c, 0x01, "Write error recovered with auto-reallocation" }, - { 0x0c, 0x02, "Write error - auto-reallocation failed" }, - { 0x10, 0x00, "Id CRC or ECC error" }, - { 0x10, 0x04, "Recovered data with LEC" }, - { 0x11, 0x00, "Unrecovered read error" }, - { 0x11, 0x01, "Read retries exhausted" }, - { 0x11, 0x02, "Error too long to correct" }, - { 0x11, 0x03, "Multiple read errors" }, - { 0x11, 0x04, "Unrecovered read error - auto-reallocate failed" }, - { 0x11, 0x05, "L-EC uncorrectable error" }, - { 0x11, 0x06, "CIRC unrecovered error" }, - { 0x11, 0x07, "Data resynchronization error" }, - { 0x11, 0x08, "Incomplete block read" }, - { 0x11, 0x09, "No gap found" }, - { 0x11, 0x0a, "Miscorrected error" }, - { 0x11, 0x0b, "Unrecovered read error - recommend reassignment" }, - { 0x11, 0x0c, "Unrecovered read error - recommend rewrite the data" }, - { 0x12, 0x00, "Address mark not found for id field" }, - { 0x13, 0x00, "Address mark not found for data field" }, - { 0x14, 0x00, "Recorded entity not found" }, - { 0x14, 0x01, "Record not found" }, - { 0x14, 0x02, "Filemark or setmark not found" }, - { 0x14, 0x03, "End-of-data not found" }, - { 0x14, 0x04, "Block sequence error" }, - { 0x15, 0x00, "Random positioning error" }, - { 0x15, 0x01, "Mechanical positioning error" }, - { 0x15, 0x02, "Positioning error detected by read of medium" }, - { 0x16, 0x00, "Data synchronization mark error" }, - { 0x17, 0x00, "Recovered data with no error correction applied" }, - { 0x17, 0x01, "Recovered data with retries" }, - { 0x17, 0x02, "Recovered data with positive head offset" }, - { 0x17, 0x03, "Recovered data with negative head offset" }, - { 0x17, 0x04, "Recovered data with retries and/or CIRC applied" }, - { 0x17, 0x05, "Recovered data using previous sector id" }, - { 0x17, 0x06, "Recovered data without ECC - data auto-reallocated" }, - { 0x17, 0x07, "Recovered data without ECC - recommend reassignment" }, - { 0x18, 0x00, "Recovered data with error correction applied" }, - { 0x18, 0x01, "Recovered data with error correction and retries applied" }, - { 0x18, 0x02, "Recovered data - data auto-reallocated" }, - { 0x18, 0x03, "Recovered data with CIRC" }, - { 0x18, 0x05, "Recovered data - recommended reassignment" }, - { 0x19, 0x00, "Defect list error" }, - { 0x19, 0x01, "Defect list not available" }, - { 0x19, 0x02, "Defect list error in primary list" }, - { 0x19, 0x03, "Defect list error in grown list" }, - { 0x1a, 0x00, "Parameter list length error" }, - { 0x1b, 0x00, "Synchronous data transfer error" }, - { 0x1c, 0x00, "Defect list not found" }, - { 0x1c, 0x01, "Primary defect list not found" }, - { 0x1c, 0x02, "Grown defect list not found" }, - { 0x1d, 0x00, "Miscompare during verify operation" }, - { 0x1e, 0x00, "Recovered id with ECC correction" }, - { 0x20, 0x00, "Invalid command operation code" }, - { 0x21, 0x00, "Logical block address out of range" }, - { 0x21, 0x01, "Invalid element address" }, - { 0x22, 0x00, "Illegal function" }, - { 0x24, 0x00, "Invalid field in CDB" }, - { 0x24, 0x02, "Log parameters changed" }, - { 0x25, 0x00, "Logical unit not supported" }, - { 0x26, 0x00, "Invalid field in parameter list" }, - { 0x26, 0x01, "Parameter not supported" }, - { 0x26, 0x02, "Parameter value invalid" }, - { 0x26, 0x03, "Threshold parameters not supported" }, - { 0x27, 0x00, "Write protected" }, - { 0x28, 0x00, "Not ready to ready transition (medium may have changed)" }, - { 0x28, 0x01, "Import or export element accessed" }, - { 0x29, 0x00, "Power on, reset, or bus device reset occurred" }, - { 0x2a, 0x00, "Parameters changed" }, - { 0x2a, 0x01, "Mode parameters changed" }, - { 0x2b, 0x00, "Copy cannot execute since host cannot disconnect" }, - { 0x2c, 0x00, "Command sequence error" }, - { 0x2c, 0x01, "Too many windows specified" }, - { 0x2c, 0x02, "Invalid combination of windows specified" }, - { 0x2d, 0x00, "Overwrite error on update in place" }, - { 0x2f, 0x00, "Commands cleared by another initiator" }, - { 0x30, 0x00, "Incompatible medium installed" }, - { 0x30, 0x01, "Cannot read medium - unknown format" }, - { 0x30, 0x02, "Cannot read medium - incompatible format" }, - { 0x30, 0x03, "Cleaning cartridge installed" }, - { 0x31, 0x00, "Medium format corrupted" }, - { 0x31, 0x01, "Format command failed" }, - { 0x32, 0x00, "No defect spare location available" }, - { 0x32, 0x01, "Defect list update failure" }, - { 0x33, 0x00, "Tape length error" }, - { 0x36, 0x00, "Ribbon, ink, or toner failure" }, - { 0x37, 0x00, "Rounded parameter" }, - { 0x39, 0x00, "Saving parameters not supported" }, - { 0x3a, 0x00, "Medium not present" }, - { 0x3b, 0x00, "Sequential positioning error" }, - { 0x3b, 0x01, "Tape position error at beginning of medium" }, - { 0x3b, 0x02, "Tape position error at end of medium" }, - { 0x3b, 0x03, "Tape or electronic vertical forms unit not ready" }, - { 0x3b, 0x04, "Slew failure" }, - { 0x3b, 0x05, "Paper jam" }, - { 0x3b, 0x06, "Failed to sense top-of-form" }, - { 0x3b, 0x07, "Failed to sense bottom-of-form" }, - { 0x3b, 0x08, "Reposition error" }, - { 0x3b, 0x09, "Read past end of medium" }, - { 0x3b, 0x0a, "Read past beginning of medium" }, - { 0x3b, 0x0b, "Position past end of medium" }, - { 0x3b, 0x0c, "Position past beginning of medium" }, - { 0x3b, 0x0d, "Medium destination element full" }, - { 0x3b, 0x0e, "Medium source element empty" }, - { 0x3d, 0x00, "Invalid bits in identify message" }, - { 0x3e, 0x00, "Logical unit has not self-configured yet" }, - { 0x3f, 0x00, "Target operating conditions have changed" }, - { 0x3f, 0x01, "Microcode has been changed" }, - { 0x3f, 0x02, "Changed operating definition" }, - { 0x3f, 0x03, "Inquiry data has changed" }, - { 0x40, 0x00, "RAM failure" }, - { 0x40, 0xff, "Diagnostic failure on component <NN>" }, - { 0x41, 0x00, "Data path failure" }, - { 0x42, 0x00, "Power on or self-test failure" }, - { 0x43, 0x00, "Message error" }, - { 0x44, 0x00, "Internal target failure" }, - { 0x45, 0x00, "Select or reselect failure" }, - { 0x46, 0x00, "Unsuccessful soft reset" }, - { 0x47, 0x00, "SCSI parity error" }, - { 0x48, 0x00, "Initiator detected message received" }, - { 0x49, 0x00, "Invalid message error" }, - { 0x4a, 0x00, "Command phase error" }, - { 0x4b, 0x00, "Data phase error" }, - { 0x4c, 0x00, "Logical unit failed self-configuration" }, - { 0x4e, 0x00, "Overlapped commands attempted" }, - { 0x50, 0x00, "Write append error" }, - { 0x50, 0x01, "Write append position error" }, - { 0x50, 0x02, "Position error related to timing" }, - { 0x51, 0x00, "Erase failure" }, - { 0x52, 0x00, "Cartridge fault" }, - { 0x53, 0x00, "Media load or eject failed" }, - { 0x53, 0x01, "Unload tape failure" }, - { 0x53, 0x02, "Medium removal prevented" }, - { 0x54, 0x00, "SCSI to host system interface failure" }, - { 0x55, 0x00, "System resource failure" }, - { 0x57, 0x00, "Unable to recover table-of-contents" }, - { 0x58, 0x00, "Generation does not exist" }, - { 0x59, 0x00, "Updated block read" }, - { 0x5a, 0x00, "Operator request or state change input (unspecified)" }, - { 0x5a, 0x01, "Operator medium removal request" }, - { 0x5a, 0x02, "Operator selected write protect" }, - { 0x5a, 0x03, "Operator selected write permit" }, - { 0x5b, 0x00, "Log exception" }, - { 0x5b, 0x01, "Threshold condition met" }, - { 0x5b, 0x02, "Log counter at maximum" }, - { 0x5b, 0x03, "Log list codes exhausted" }, - { 0x5c, 0x00, "RPL status change" }, - { 0x5c, 0x01, "Spindles synchronized" }, - { 0x5c, 0x02, "Spindles not synchronized" }, - { 0x60, 0x00, "Lamp failure" }, - { 0x61, 0x00, "Video acquisition error" }, - { 0x61, 0x01, "Unable to acquire video" }, - { 0x61, 0x02, "Out of focus" }, - { 0x62, 0x00, "Scan head positioning error" }, - { 0x63, 0x00, "End of user area encountered on this track" }, - { 0x64, 0x00, "Illegal mode for this track" }, - { 0, 0, 0} -}; - -void scsi_print_add_sense_keys(key, qualif) - register unsigned key, qualif; -{ - register struct addtl_sns_keys_msg *msg; - - for (msg = addtl_sns_msgs; msg->means; msg++) { - if (msg->byte12 != key) continue; - if ((msg->byte12 == 0x40) && qualif) { - printf(", %s, NN=x%x", msg->means, qualif); - return; - } - if (msg->byte13 == qualif) { - printf(" %s", msg->means); - return; - } - }; - printf(", Unknown additional sense keys: 0x%x 0x%x\n", key, qualif); -} -#endif /* NSCSI > 0 */ diff --git a/scsi/scsi_comm.c b/scsi/scsi_comm.c deleted file mode 100644 index 1f0095a..0000000 --- a/scsi/scsi_comm.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_comm.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Middle layer of the SCSI driver: SCSI protocol implementation - * - * This file contains code for SCSI commands for COMMUNICATION devices. - */ - -#include <mach/std_types.h> -#include <scsi/compat_30.h> - -#include <scsi/scsi.h> -#include <scsi/scsi_defs.h> - -#if (NSCSI > 0) - -char *sccomm_name( - boolean_t internal) -{ - return internal ? "cz" : "comm"; -} - -void scsi_get_message( - register target_info_t *tgt, - io_req_t ior) -{ - scsi_cmd_read_t *cmd; - register unsigned len, max; - - max = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - - len = ior->io_count; - if (len > max) { - ior->io_residual = len - max; - len = max; - } - - cmd = (scsi_cmd_read_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_GET_MESSAGE; - cmd->scsi_cmd_lun_and_lba1 = tgt->lun << SCSI_LUN_SHIFT; - cmd->scsi_cmd_lba2 = len >> 16; - cmd->scsi_cmd_lba3 = len >> 8; - cmd->scsi_cmd_xfer_len = len; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_GET_MESSAGE; - - scsi_go(tgt, sizeof(*cmd), len, FALSE); -} - -void scsi_send_message( - register target_info_t *tgt, - io_req_t ior) -{ - scsi_cmd_write_t *cmd; - register unsigned len, max; - - len = ior->io_count; - max = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - - if (len > max) { - ior->io_residual = len - max; - len = max; - } - - cmd = (scsi_cmd_write_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_SEND_MESSAGE; - cmd->scsi_cmd_lun_and_lba1 = tgt->lun << SCSI_LUN_SHIFT; - cmd->scsi_cmd_lba2 = len >> 16; - cmd->scsi_cmd_lba3 = len >> 8; - cmd->scsi_cmd_xfer_len = len; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_SEND_MESSAGE; - - scsi_go(tgt, sizeof(*cmd), 0, FALSE); -} - - -#if 0 -/* For now, these are not needed */ -scsi_get_message_long -scsi_get_message_vlong -scsi_send_message_long -scsi_send_message_vlong -#endif - -#endif /* NSCSI > 0 */ diff --git a/scsi/scsi_cpu.c b/scsi/scsi_cpu.c deleted file mode 100644 index 979847c..0000000 --- a/scsi/scsi_cpu.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_cpu.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Middle layer of the SCSI driver: SCSI protocol implementation - * - * This file contains code for SCSI commands for PROCESSOR devices. - */ - -#include <mach/std_types.h> -#include <scsi/compat_30.h> - -#include <scsi/scsi.h> -#include <scsi/scsi2.h> -#include <scsi/scsi_defs.h> - -#if (NSCSI > 0) - -char *sccpu_name(internal) - boolean_t internal; -{ - return internal ? "sc" : "cpu"; -} - -void scsi_send( tgt, ior) - register target_info_t *tgt; - io_req_t ior; -{ - scsi_cmd_write_t *cmd; - unsigned len; /* in bytes */ - unsigned int max_dma_data; - - max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - - len = ior->io_count; - if (len > max_dma_data) - len = max_dma_data; - if (len < tgt->block_size) - len = tgt->block_size; - - cmd = (scsi_cmd_write_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_SEND; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba2 = len >> 16; - cmd->scsi_cmd_lba3 = len >> 8; - cmd->scsi_cmd_xfer_len = len; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_SEND; - - scsi_go(tgt, sizeof(*cmd), 0, FALSE); -} - -void scsi_receive( tgt, ior) - register target_info_t *tgt; - io_req_t ior; -{ - scsi_cmd_read_t *cmd; - register unsigned len; - unsigned int max_dma_data; - - max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - - len = ior->io_count; - if (len > max_dma_data) - len = max_dma_data; - if (len < tgt->block_size) - len = tgt->block_size; - - cmd = (scsi_cmd_read_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_RECEIVE; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba2 = len >> 16; - cmd->scsi_cmd_lba3 = len >> 8; - cmd->scsi_cmd_xfer_len = len; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_RECEIVE; - - scsi_go(tgt, sizeof(*cmd), len, FALSE); -} - -#endif /* NSCSI > 0 */ diff --git a/scsi/scsi_defs.h b/scsi/scsi_defs.h deleted file mode 100644 index c98bc85..0000000 --- a/scsi/scsi_defs.h +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1993-1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_defs.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 9/90 - * - * Controller-independent definitions for the SCSI driver - */ - -#ifndef _SCSI_SCSI_DEFS_H_ -#define _SCSI_SCSI_DEFS_H_ - -#include <kern/queue.h> -#include <kern/lock.h> - -#include <rz_labels.h> - -#define await(event) sleep(event,0) -extern void wakeup(); - -typedef vm_offset_t opaque_t; /* should be elsewhere */ - -/* - * Internal error codes, and return values - * XXX use the mach/error.h scheme XXX - */ -typedef unsigned int scsi_ret_t; - -#define SCSI_ERR_GRAVITY(x) ((unsigned)(x)&0xf0000000U) -#define SCSI_ERR_GRAVE 0x80000000U -#define SCSI_ERR_BAD 0x40000000 - -#define SCSI_ERR_CLASS(x) ((unsigned)(x)&0x0fffffffU) -#define SCSI_ERR_STATUS 0x00000001 -#define SCSI_ERR_SENSE 0x00000002 -#define SCSI_ERR_MSEL 0x00000004 - -extern void scsi_error(/* target_info_t *, unsigned, unsigned */); - -#define SCSI_RET_IN_PROGRESS 0x00 -#define SCSI_RET_SUCCESS 0x01 -#define SCSI_RET_RETRY 0x02 -#define SCSI_RET_NEED_SENSE 0x04 -#define SCSI_RET_ABORTED 0x08 -#define SCSI_RET_DEVICE_DOWN 0x10 - -/* - * Device-specific information kept by driver - */ -#define MAX_SCSI_PARTS 32 /* maximum partitions on a disk;can be larger */ -typedef struct { - struct disklabel l; /* NOT accurate. partitions stored below */ - struct { - unsigned int badblockno; - unsigned int save_rec; - char *save_addr; - int save_count; - int save_resid; - int retry_count; - } b; -#if 0 /* no longer used by partition code */ - int labelsector; - int labeloffset; -#endif 0 - struct diskpart scsi_array[MAX_SCSI_PARTS]; /* new partition info */ -} scsi_disk_info_t; - -typedef struct { - boolean_t read_only; - unsigned int speed; - unsigned int density; - unsigned int maxreclen; - boolean_t fixed_size; -} scsi_tape_info_t; - -typedef struct { - char req_pending; - char req_id; - char req_lun; - char req_cmd; - unsigned int req_len; - /* more later */ -} scsi_processor_info_t; - -typedef struct { - void *result; - boolean_t result_available; - int result_size; - struct red_list *violates_standards; -} scsi_cdrom_info_t; - -typedef struct { -# define SCSI_MAX_COMM_TTYS 16 - struct tty *tty[SCSI_MAX_COMM_TTYS]; - io_req_t ior; -} scsi_comm_info_t; - -/* - * Device descriptor - */ - -#define SCSI_TARGET_NAME_LEN 8+16+4+8 /* our way to keep it */ - -typedef struct target_info { - queue_chain_t links; /* to queue for bus */ - io_req_t ior; /* what we are doing */ - - unsigned int flags; -#define TGT_DID_SYNCH 0x00000001 /* finished the synch neg */ -#define TGT_TRY_SYNCH 0x00000002 /* do the synch negotiation */ -#define TGT_FULLY_PROBED 0x00000004 /* can sleep to wait */ -#define TGT_ONLINE 0x00000008 /* did the once-only stuff */ -#define TGT_ALIVE 0x00000010 -#define TGT_BBR_ACTIVE 0x00000020 /* bad block replc in progress */ -#define TGT_DISCONNECTED 0x00000040 /* waiting for reconnect */ -#define TGT_WRITTEN_TO 0x00000080 /* tapes: needs a filemark on close */ -#define TGT_REWIND_ON_CLOSE 0x00000100 /* tapes: rewind */ -#define TGT_BIG 0x00000200 /* disks: > 1Gb, use long R/W */ -#define TGT_REMOVABLE_MEDIA 0x00000400 /* e.g. floppy, cd-rom,.. */ -#define TGT_READONLY 0x00000800 /* cd-rom, scanner, .. */ -#define TGT_OPTIONAL_CMD 0x00001000 /* optional cmd, ignore errors */ -#define TGT_WRITE_LABEL 0x00002000 /* disks: enable overwriting of label */ -#define TGT_US 0x00004000 /* our desc, when target role */ - -#define TGT_HW_SPECIFIC_BITS 0xffff0000U /* see specific HBA */ - char *hw_state; /* opaque */ - char *dma_ptr; - char *cmd_ptr; - struct scsi_devsw_struct *dev_ops; /* circularity */ - struct target_info *next_lun; /* if multi-LUN */ - char target_id; - char unit_no; - unsigned char sync_period; - unsigned char sync_offset; - decl_simple_lock_data(,target_lock) -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - struct fdma fdma; -#endif /*MACH_KERNEL*/ - /* - * State info kept while waiting to seize bus, either for first - * selection or while in disconnected state - */ - struct { - struct script *script; - int (*handler)(); - unsigned int out_count; - unsigned int in_count; - unsigned int copy_count; /* optional */ - unsigned int dma_offset; - unsigned char identify; - unsigned char cmd_count; - unsigned char hba_dep[2]; - } transient_state; - unsigned int block_size; - volatile char done; - unsigned char cur_cmd; - unsigned char lun; - char masterno; - char tgt_name[SCSI_TARGET_NAME_LEN]; - union { - scsi_disk_info_t disk; - scsi_tape_info_t tape; - scsi_cdrom_info_t cdrom; - scsi_processor_info_t cpu; - scsi_comm_info_t comm; - } dev_info; -} target_info_t; - - -/* - * Device-specific operations - */ -typedef struct scsi_devsw_struct { - char *(*driver_name)(boolean_t); /* my driver's name */ - void (*optimize)(target_info_t *); /* tune up internal params */ - scsi_ret_t (*open)(target_info_t *,io_req_t);/* open time ops */ - scsi_ret_t (*close)(target_info_t *); /* close time ops */ - int (*strategy)(io_req_t); /* sort/start routine */ - void (*restart)(target_info_t *, - boolean_t); /* completion routine */ - io_return_t (*get_status)(int, - target_info_t *, - dev_flavor_t, - dev_status_t, - natural_t *); /* specialization */ - io_return_t (*set_status)(int, - target_info_t *, - dev_flavor_t, - dev_status_t, - natural_t); /* specialization */ -} scsi_devsw_t; - -#define SCSI_OPTIMIZE_NULL ((void (*)(target_info_t *)) 0) -#define SCSI_OPEN_NULL ((scsi_ret_t (*)(target_info_t *,io_req_t)) 0) -#define SCSI_CLOSE_NULL ((scsi_ret_t (*)(target_info_t *)) 0) - -extern scsi_devsw_t scsi_devsw[]; - -/* - * HBA descriptor - */ - -typedef struct { - /* initiator (us) state */ - unsigned char initiator_id; - unsigned char masterno; - unsigned int max_dma_data; - char *hw_state; /* opaque */ - int (*go)(); - void (*watchdog)(); - boolean_t (*probe)(); - /* per-target state */ - target_info_t *target[8]; -} scsi_softc_t; - -extern scsi_softc_t *scsi_softc[]; -extern scsi_softc_t *scsi_master_alloc(/* int unit */); -extern target_info_t *scsi_slave_alloc(/* int unit, int slave, char *hw */); - -#define BGET(d,mid,id) (d[mid] & (1 << id)) /* bitmap ops */ -#define BSET(d,mid,id) d[mid] |= (1 << id) -#define BCLR(d,mid,id) d[mid] &= ~(1 << id) - -extern unsigned char scsi_no_synchronous_xfer[]; /* one bitmap per ctlr */ -extern unsigned char scsi_use_long_form[]; /* one bitmap per ctlr */ -extern unsigned char scsi_might_disconnect[]; /* one bitmap per ctlr */ -extern unsigned char scsi_should_disconnect[]; /* one bitmap per ctlr */ -extern unsigned char scsi_initiator_id[]; /* one id per ctlr */ - -extern boolean_t scsi_exabyte_filemarks; -extern boolean_t scsi_no_automatic_bbr; -extern int scsi_bbr_retries; -extern int scsi_watchdog_period; -extern int scsi_delay_after_reset; -extern unsigned int scsi_per_target_virtual; /* 2.5 only */ - -extern int scsi_debug; - -/* - * HBA-independent Watchdog - */ -typedef struct { - - unsigned short reset_count; - char nactive; - - char watchdog_state; - -#define SCSI_WD_INACTIVE 0 -#define SCSI_WD_ACTIVE 1 -#define SCSI_WD_EXPIRED 2 - - int (*reset)(); - -} watchdog_t; - -extern void scsi_watchdog( watchdog_t* ); - -#endif _SCSI_SCSI_DEFS_H_ diff --git a/scsi/scsi_disk.c b/scsi/scsi_disk.c deleted file mode 100644 index 99bbe76..0000000 --- a/scsi/scsi_disk.c +++ /dev/null @@ -1,624 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_disk.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Middle layer of the SCSI driver: SCSI protocol implementation - * - * This file contains code for SCSI commands for DISK devices. - */ - -#include <string.h> - -#include <mach/std_types.h> -#include <scsi/compat_30.h> - -#include <scsi/scsi.h> -#include <scsi/scsi2.h> -#include <scsi/scsi_defs.h> - -#if (NSCSI > 0) - - -char *scdisk_name(internal) - boolean_t internal; -{ - return internal ? "rz" : "disk"; -} - -/* - * SCSI commands partially specific to disks - */ -void scdisk_read( tgt, secno, ior) - register target_info_t *tgt; - register unsigned int secno; - io_req_t ior; -{ - scsi_cmd_read_t *cmd; - register unsigned len; - unsigned int max_dma_data; - - max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - - len = ior->io_count; - if (len > max_dma_data) - len = max_dma_data; - if (len < tgt->block_size) - len = tgt->block_size; - - cmd = (scsi_cmd_read_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_READ; - cmd->scsi_cmd_lun_and_lba1 = (secno>>16)&SCSI_LBA_MASK; - cmd->scsi_cmd_lba2 = (secno>> 8)&0xff; - cmd->scsi_cmd_lba3 = (secno )&0xff; - cmd->scsi_cmd_xfer_len = len / tgt->block_size; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_READ; - - scsi_go(tgt, sizeof(*cmd), len, FALSE); -} - -void scdisk_write( tgt, secno, ior) - register target_info_t *tgt; - register unsigned int secno; - io_req_t ior; -{ - scsi_cmd_write_t *cmd; - unsigned len; /* in bytes */ - unsigned int max_dma_data; - - max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - - len = ior->io_count; - if (len > max_dma_data) - len = max_dma_data; - if (len < tgt->block_size) - len = tgt->block_size; - - cmd = (scsi_cmd_write_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_WRITE; - cmd->scsi_cmd_lun_and_lba1 = (secno>>16)&SCSI_LBA_MASK; - cmd->scsi_cmd_lba2 = (secno>> 8)&0xff; - cmd->scsi_cmd_lba3 = (secno )&0xff; - cmd->scsi_cmd_xfer_len = len / tgt->block_size; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_WRITE; - - scsi_go(tgt, sizeof(*cmd), 0, FALSE); -} - - -int scdisk_mode_select(tgt, lbn, ior, mdata, mlen, save) - register target_info_t *tgt; - register int lbn; - io_req_t ior; - char *mdata; - int mlen, save; -{ - scsi_cmd_mode_select_t *cmd; - scsi_mode_select_param_t *parm; - - bzero(tgt->cmd_ptr, sizeof(*cmd) + sizeof(*parm)); - cmd = (scsi_cmd_mode_select_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_MODE_SELECT; - cmd->scsi_cmd_lun_and_lba1 = SCSI_CMD_MSL_PF; /* XXX only if... */ - cmd->scsi_cmd_xfer_len = sizeof(scsi_mode_select_param_t);/* no vuq */ - - parm = (scsi_mode_select_param_t*) (cmd + 1); - if (mdata) { - cmd->scsi_cmd_xfer_len = mlen; - bcopy(mdata, (char*)parm, mlen); - if (save) - cmd->scsi_cmd_lun_and_lba1 |= SCSI_CMD_MSL_SP; - } else { - /* parm->medium_type = if (floppy)disk.. */ - parm->desc_len = 8; - /* this really is the LBN */ - parm->descs[0].density_code = 0;/* XXX default XXX */ - parm->descs[0].reclen1 = (lbn>>16)&0xff; - parm->descs[0].reclen2 = (lbn>> 8)&0xff; - parm->descs[0].reclen3 = (lbn )&0xff; - mlen = sizeof(*parm); - } - - tgt->cur_cmd = SCSI_CMD_MODE_SELECT; - - scsi_go_and_wait(tgt, sizeof(*cmd) + mlen, 0, ior); - - return tgt->done; -} - -/* - * SCSI commands fully specific to disks - */ -int scsi_read_capacity( tgt, lbn, ior) - register target_info_t *tgt; - int lbn; - io_req_t ior; -{ - scsi_cmd_read_capacity_t *cmd; - - bzero(tgt->cmd_ptr, sizeof(*cmd)); - cmd = (scsi_cmd_read_capacity_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_READ_CAPACITY; - /* all zeroes, unless... */ - if (lbn) { - cmd->scsi_cmd_rcap_flags = SCSI_CMD_RCAP_PMI; - cmd->scsi_cmd_lba1 = (lbn>>24); - cmd->scsi_cmd_lba2 = (lbn>>16)&0xff; - cmd->scsi_cmd_lba3 = (lbn>> 8)&0xff; - cmd->scsi_cmd_lba4 = (lbn )&0xff; - } - - tgt->cur_cmd = SCSI_CMD_READ_CAPACITY; - - scsi_go_and_wait(tgt, sizeof(*cmd), sizeof(scsi_rcap_data_t),ior); - - return tgt->done; -} - -void scsi_reassign_blocks( tgt, defect_list, n_defects, ior) - register target_info_t *tgt; - unsigned int *defect_list; /* In ascending order ! */ - int n_defects; - io_req_t ior; -{ - scsi_cmd_reassign_blocks_t *cmd; - scsi_Ldefect_data_t *parm; - - cmd = (scsi_cmd_reassign_blocks_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_REASSIGN_BLOCKS; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_xfer_len = 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - parm = (scsi_Ldefect_data_t *) (cmd + 1); - parm->res1 = parm->res2 = 0; - n_defects *= 4; /* in 4-byte-ints */ - parm->list_len_msb = n_defects >> 8; - parm->list_len_lsb = n_defects; - bcopy((char*)defect_list, (char*)parm->defects, n_defects); - - tgt->cur_cmd = SCSI_CMD_REASSIGN_BLOCKS; - - scsi_go(tgt, sizeof(*cmd) + sizeof(*parm) + (n_defects - 4), 0, FALSE); -} - -void scsi_medium_removal( tgt, allow, ior) - register target_info_t *tgt; - boolean_t allow; - io_req_t ior; -{ - scsi_cmd_medium_removal_t *cmd; - - cmd = (scsi_cmd_medium_removal_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_PREVENT_ALLOW_REMOVAL; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_pa_prevent = allow ? 0 : 1; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - - tgt->cur_cmd = SCSI_CMD_PREVENT_ALLOW_REMOVAL; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); -} - -int scsi_format_unit( tgt, mode, vuqe, intlv, ior) - register target_info_t *tgt; - int mode, vuqe; - register unsigned int intlv; - io_req_t ior; -{ - scsi_cmd_format_t *cmd; - char *parms; - - cmd = (scsi_cmd_format_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_FORMAT_UNIT; - cmd->scsi_cmd_lun_and_lba1 = - mode & (SCSI_CMD_FMT_FMTDATA|SCSI_CMD_FMT_CMPLIST|SCSI_CMD_FMT_LIST_TYPE); - cmd->scsi_cmd_lba2 = vuqe; - cmd->scsi_cmd_lba3 = intlv >> 8; - cmd->scsi_cmd_xfer_len = intlv; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - parms = (char*) cmd + 1; - if (ior->io_count) - bcopy(ior->io_data, parms, ior->io_count); - else - bzero(parms, 0xff - sizeof(*cmd)); - - tgt->cur_cmd = SCSI_CMD_FORMAT_UNIT; - - scsi_go_and_wait(tgt, sizeof(*cmd) + ior->io_count, 0, ior); - return tgt->done; -} - - -/* Group 1 Commands */ - -void scsi_long_read( tgt, secno, ior) - register target_info_t *tgt; - register unsigned int secno; - io_req_t ior; -{ - scsi_cmd_long_read_t *cmd; - register unsigned len, n_blks; - unsigned int max_dma_data; - - max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - - len = ior->io_count; - if (len > max_dma_data) - len = max_dma_data; - if (len < tgt->block_size) - len = tgt->block_size; - n_blks = len /tgt->block_size; - - cmd = (scsi_cmd_long_read_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_LONG_READ; - cmd->scsi_cmd_lun_and_relbit = 0; - cmd->scsi_cmd_lba1 = secno >> 24; - cmd->scsi_cmd_lba2 = secno >> 16; - cmd->scsi_cmd_lba3 = secno >> 8; - cmd->scsi_cmd_lba4 = secno; - cmd->scsi_cmd_xxx = 0; - cmd->scsi_cmd_xfer_len_1 = n_blks >> 8; - cmd->scsi_cmd_xfer_len_2 = n_blks; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_LONG_READ; - - scsi_go(tgt, sizeof(*cmd), len, FALSE); -} - -void scsi_long_write( tgt, secno, ior) - register target_info_t *tgt; - register unsigned int secno; - io_req_t ior; -{ - scsi_cmd_long_write_t *cmd; - unsigned len; /* in bytes */ - unsigned int max_dma_data, n_blks; - - max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - - len = ior->io_count; - if (len > max_dma_data) - len = max_dma_data; - if (len < tgt->block_size) - len = tgt->block_size; - n_blks = len /tgt->block_size; - - cmd = (scsi_cmd_long_write_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_LONG_WRITE; - cmd->scsi_cmd_lun_and_relbit = 0; - cmd->scsi_cmd_lba1 = secno >> 24; - cmd->scsi_cmd_lba2 = secno >> 16; - cmd->scsi_cmd_lba3 = secno >> 8; - cmd->scsi_cmd_lba4 = secno; - cmd->scsi_cmd_xxx = 0; - cmd->scsi_cmd_xfer_len_1 = n_blks >> 8; - cmd->scsi_cmd_xfer_len_2 = n_blks; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_LONG_WRITE; - - scsi_go(tgt, sizeof(*cmd), 0, FALSE); -} - -int scdisk_verify( tgt, secno, nsectrs, ior) - register target_info_t *tgt; - int secno, nsectrs; - io_req_t ior; -{ - scsi_cmd_verify_long_t *cmd; - int len; - - len = ior->io_count; - - cmd = (scsi_cmd_verify_long_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_VERIFY_1; - cmd->scsi_cmd_lun_and_relbit = len ? SCSI_CMD_VFY_BYTCHK : 0; - cmd->scsi_cmd_lba1 = secno >> 24; - cmd->scsi_cmd_lba2 = secno >> 16; - cmd->scsi_cmd_lba3 = secno >> 8; - cmd->scsi_cmd_lba4 = secno; - cmd->scsi_cmd_xxx = 0; - cmd->scsi_cmd_xfer_len_1 = (nsectrs) >> 8; - cmd->scsi_cmd_xfer_len_2 = nsectrs; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_VERIFY_1; - - scsi_go_and_wait(tgt, sizeof(*cmd) + len, 0, ior); - return tgt->done; -} - - -int scsi_read_defect( tgt, mode, ior) - register target_info_t *tgt; - register unsigned int mode; - io_req_t ior; -{ - scsi_cmd_long_read_t *cmd; - register unsigned len; - - len = ior->io_count; - if (len > 0xffff) - len = 0xffff; - - cmd = (scsi_cmd_read_defect_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_READ_DEFECT_DATA; - cmd->scsi_cmd_lun_and_relbit = 0; - cmd->scsi_cmd_lba1 = mode & 0x1f; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_lba4 = 0; - cmd->scsi_cmd_xxx = 0; - cmd->scsi_cmd_xfer_len_1 = (len) >> 8; - cmd->scsi_cmd_xfer_len_2 = (len); - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - /* ++ HACK Alert */ -/* tgt->cur_cmd = SCSI_CMD_READ_DEFECT_DATA;*/ - tgt->cur_cmd = SCSI_CMD_LONG_READ; - /* -- HACK Alert */ - - scsi_go(tgt, sizeof(*cmd), len, FALSE); - iowait(ior); - return tgt->done; -} - - -#if 0 /* unused commands */ -scsi_rezero_unit( tgt, ior) - register target_info_t *tgt; - io_req_t ior; -{ - scsi_cmd_rezero_t *cmd; - - cmd = (scsi_cmd_rezero_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_REZERO_UNIT; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_xfer_len = 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - - tgt->cur_cmd = SCSI_CMD_REZERO_UNIT; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - -} - -scsi_seek( tgt, where, ior) - register target_info_t *tgt; - register unsigned int where; - io_req_t ior; -{ - scsi_cmd_seek_t *cmd; - - cmd = (scsi_cmd_seek_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_SEEK; - cmd->scsi_cmd_lun_and_lba1 = (where >> 16) & 0x1f; - cmd->scsi_cmd_lba2 = where >> 8; - cmd->scsi_cmd_lba3 = where; - cmd->scsi_cmd_xfer_len = 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - - tgt->cur_cmd = SCSI_CMD_SEEK; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - -} - -scsi_reserve( tgt, len, id, mode, ior) - register target_info_t *tgt; - register unsigned int len; - unsigned char id; - io_req_t ior; -{ - scsi_cmd_reserve_t *cmd; - - cmd = (scsi_cmd_reserve_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_RESERVE; - cmd->scsi_cmd_lun_and_lba1 = mode & 0x1f; - cmd->scsi_cmd_reserve_id = id; - cmd->scsi_cmd_extent_llen1 = len >> 8; - cmd->scsi_cmd_extent_llen2 = len; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - - tgt->cur_cmd = SCSI_CMD_RESERVE; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - -} - -scsi_release( tgt, id, mode, ior) - register target_info_t *tgt; - unsigned char id, mode; - io_req_t ior; -{ - scsi_cmd_release_t *cmd; - - cmd = (scsi_cmd_release_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_RELEASE; - cmd->scsi_cmd_lun_and_lba1 = mode & 0x1f; - cmd->scsi_cmd_reserve_id = id; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_xfer_len = 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - - tgt->cur_cmd = SCSI_CMD_RELEASE; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - -} - - -/* Group 1 Commands */ - -scsi_long_seek( tgt, secno, ior) - register target_info_t *tgt; - io_req_t ior; -{ - scsi_cmd_long_seek_t *cmd; - - cmd = (scsi_cmd_long_seek_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_LONG_SEEK; - cmd->scsi_cmd_lun_and_relbit = 0; - cmd->scsi_cmd_lba1 = secno >> 24; - cmd->scsi_cmd_lba2 = secno >> 16; - cmd->scsi_cmd_lba3 = secno >> 8; - cmd->scsi_cmd_lba4 = secno; - cmd->scsi_cmd_xxx = 0; - cmd->scsi_cmd_xfer_len_1 = 0; - cmd->scsi_cmd_xfer_len_2 = 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_LONG_SEEK; - - scsi_go(tgt, sizeof(*cmd), 0, FALSE); -} - -scsi_write_verify( tgt, secno, ior) - register target_info_t *tgt; - io_req_t ior; -{ - scsi_cmd_write_vfy_t *cmd; - unsigned len; /* in bytes */ - unsigned int max_dma_data, n_blks; - - max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - - len = ior->io_count; - if (len > max_dma_data) - len = max_dma_data; - if (len < tgt->block_size) - len = tgt->block_size; - n_blks = len / tgt->block_size; - - cmd = (scsi_cmd_write_vfy_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_WRITE_AND_VERIFY; - cmd->scsi_cmd_lun_and_relbit = SCSI_CMD_VFY_BYTCHK; - cmd->scsi_cmd_lba1 = secno >> 24; - cmd->scsi_cmd_lba2 = secno >> 16; - cmd->scsi_cmd_lba3 = secno >> 8; - cmd->scsi_cmd_lba4 = secno; - cmd->scsi_cmd_xxx = 0; - cmd->scsi_cmd_xfer_len_1 = n_blks >> 8; - cmd->scsi_cmd_xfer_len_2 = n_blks; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_WRITE_AND_VERIFY; - - scsi_go(tgt, sizeof(*cmd), 0, FALSE); -} - -scsi_search_data( tgt, secno, how, flags, ior) - register target_info_t *tgt; - io_req_t ior; -{ - scsi_cmd_search_t *cmd; - unsigned len; /* in bytes */ - unsigned int max_dma_data, n_blks; - - max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - - if (how != SCSI_CMD_SEARCH_HIGH && - how != SCSI_CMD_SEARCH_EQUAL && - how != SCSI_CMD_SEARCH_LOW) - panic("scsi_search_data"); - - len = ior->io_count; - if (len > max_dma_data) - len = max_dma_data; - n_blks = len / tgt->block_size; - - cmd = (scsi_cmd_search_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = how; - cmd->scsi_cmd_lun_and_relbit = flags & 0x1e; - cmd->scsi_cmd_lba1 = secno >> 24; - cmd->scsi_cmd_lba2 = secno >> 16; - cmd->scsi_cmd_lba3 = secno >> 8; - cmd->scsi_cmd_lba4 = secno; - cmd->scsi_cmd_xxx = 0; - cmd->scsi_cmd_xfer_len_1 = n_blks >> 8; - cmd->scsi_cmd_xfer_len_2 = n_blks; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = how; - - scsi_go(tgt, sizeof(*cmd), 0, FALSE); -} - - -scsi_set_limits( tgt, secno, nblocks, inhibit, ior) - register target_info_t *tgt; - io_req_t ior; -{ - scsi_cmd_set_limits_t *cmd; - - cmd = (scsi_cmd_set_limits_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_SET_LIMITS; - cmd->scsi_cmd_lun_and_relbit = inhibit & 0x3; - cmd->scsi_cmd_lba1 = secno >> 24; - cmd->scsi_cmd_lba2 = secno >> 16; - cmd->scsi_cmd_lba3 = secno >> 8; - cmd->scsi_cmd_lba4 = secno; - cmd->scsi_cmd_xxx = 0; - cmd->scsi_cmd_xfer_len_1 = nblocks >> 8; - cmd->scsi_cmd_xfer_len_2 = nblocks; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_SET_LIMITS; - - scsi_go(tgt, sizeof(*cmd), 0, FALSE); -} - - -#endif - -#ifdef SCSI2 -scsi_lock_cache -scsi_prefetch -scsi_read_defect_data -scsi_sync_cache -scsi_write_same -#endif SCSI2 -#endif /* NSCSI > 0 */ diff --git a/scsi/scsi_endian.h b/scsi/scsi_endian.h deleted file mode 100644 index d298a78..0000000 --- a/scsi/scsi_endian.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_endian.h - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 6/91 - * - * Byte/Bit order issues are solved here. - */ - - -#ifndef _SCSI_ENDIAN_H_ -#define _SCSI_ENDIAN_H_ 1 - -/* - * Macros to take care of bitfield placement within a byte. - * It might be possible to extend these to something that - * takes care of multibyte structures, using perhaps the - * type ("t") parameter. Someday. - */ -#if BYTE_MSF - -#define BITFIELD_2(t,a,b) t b,a -#define BITFIELD_3(t,a,b,c) t c,b,a -#define BITFIELD_4(t,a,b,c,d) t d,c,b,a -#define BITFIELD_5(t,a,b,c,d,e) t e,d,c,b,a -#define BITFIELD_6(t,a,b,c,d,e,f) t f,e,d,c,b,a -#define BITFIELD_7(t,a,b,c,d,e,f,g) t g,f,e,d,c,b,a -#define BITFIELD_8(t,a,b,c,d,e,f,g,h) t h,g,f,e,d,c,b,a - -#else /*BYTE_MSF*/ - -#define BITFIELD_2(t,a,b) t a,b -#define BITFIELD_3(t,a,b,c) t a,b,c -#define BITFIELD_4(t,a,b,c,d) t a,b,c,d -#define BITFIELD_5(t,a,b,c,d,e) t a,b,c,d,e -#define BITFIELD_6(t,a,b,c,d,e,f) t a,b,c,d,e -#define BITFIELD_7(t,a,b,c,d,e,f,g) t a,b,c,d,e,f,g -#define BITFIELD_8(t,a,b,c,d,e,f,g,h) t a,b,c,d,e,f,g,h - -#endif /*BYTE_MSF*/ - -#endif /*_SCSI_ENDIAN_H_*/ diff --git a/scsi/scsi_jukebox.c b/scsi/scsi_jukebox.c deleted file mode 100644 index b62d0bf..0000000 --- a/scsi/scsi_jukebox.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_jukebox.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Middle layer of the SCSI driver: SCSI protocol implementation - * - * This file contains code for SCSI commands for MEDIA CHANGER devices. - */ - -#include <scsi.h> -#if (NSCSI > 0) - -#include <mach/std_types.h> - -char *scjb_name(internal) - boolean_t internal; -{ - return internal ? "jz" : "jukebox"; -} - -#if 0 -scsi_exchange_medium -scsi_init_element_status -scsi_move_medium -scsi_position_to_element -scsi_read_element_status -scsi_request_volume_address -scsi_send_volume_tag -#endif -#endif /* NSCSI > 0 */ - diff --git a/scsi/scsi_optical.c b/scsi/scsi_optical.c deleted file mode 100644 index 6188174..0000000 --- a/scsi/scsi_optical.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_optical.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Middle layer of the SCSI driver: SCSI protocol implementation - * - * This file contains code for SCSI commands for OPTICAL MEMORY devices. - */ - -#include <scsi.h> -#if (NSCSI > 0) - -#include <mach/std_types.h> - -char *scmem_name(internal) - boolean_t internal; -{ - return internal ? "rz" : "optical disk"; -} - -#if 0 -scsi_erase_long -scsi_medium_scan -scsi_read_defect_data -scsi_read_generation -scsi_read_updated_block -scsi_update_block -scsi_write_verify_long -#endif -#endif /* NSCSI > 0 */ - diff --git a/scsi/scsi_printer.c b/scsi/scsi_printer.c deleted file mode 100644 index 0ffb09a..0000000 --- a/scsi/scsi_printer.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_printer.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Middle layer of the SCSI driver: SCSI protocol implementation - * - * This file contains code for SCSI commands for PRINTER devices. - */ - -#include <scsi.h> -#if (NSCSI > 0) - -#include <mach/std_types.h> - - -char *scprt_name(internal) - boolean_t internal; -{ - return internal ? "lz" : "printer"; -} - -void scprt_optimize() -{} - -#if 0 -scsi_print -scsi_slew_and_print -scsi_flush_buffer -scsi_stop_print -#endif -#endif /* NSCSI > 0 */ diff --git a/scsi/scsi_rom.c b/scsi/scsi_rom.c deleted file mode 100644 index 1a8dec9..0000000 --- a/scsi/scsi_rom.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_rom.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Middle layer of the SCSI driver: SCSI protocol implementation - * - * This file contains code for SCSI commands for CD-ROM devices. - */ - -#include <mach/std_types.h> -#include <scsi/compat_30.h> - -#include <scsi/scsi.h> -#include <scsi/scsi2.h> -#include <scsi/scsi_defs.h> - -#if (NSCSI > 0) - -char *sccdrom_name( - boolean_t internal) -{ - return internal ? "rz" : "CD-ROM"; -} - -int scsi_pause_resume( - target_info_t *tgt, - boolean_t stop_it, - io_req_t ior) -{ - scsi_cmd_pausres_t *cmd; - - cmd = (scsi_cmd_pausres_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_PAUSE_RESUME; - cmd->scsi_cmd_lun_and_relbit = 0; - cmd->scsi_cmd_lba1 = 0; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_lba4 = 0; - cmd->scsi_cmd_xxx = 0; - cmd->scsi_cmd_xfer_len_1 = 0; - cmd->scsi_cmd_pausres_res = stop_it ? 0 : SCSI_CMD_PAUSRES_RESUME; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_PAUSE_RESUME; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - - return tgt->done; -} - -scsi_play_audio( - target_info_t *tgt, - unsigned int start, - unsigned int len, - boolean_t relative_address, - io_req_t ior) -{ - scsi_cmd_play_audio_t *cmd; - - cmd = (scsi_cmd_play_audio_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_PLAY_AUDIO; - cmd->scsi_cmd_lun_and_relbit = relative_address ? SCSI_RELADR : 0; - cmd->scsi_cmd_lba1 = start >> 24; - cmd->scsi_cmd_lba2 = start >> 16; - cmd->scsi_cmd_lba3 = start >> 8; - cmd->scsi_cmd_lba4 = start >> 0; - cmd->scsi_cmd_xxx = 0; - cmd->scsi_cmd_xfer_len_1 = len >> 8; - cmd->scsi_cmd_xfer_len_2 = len >> 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_PLAY_AUDIO; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - - return tgt->done; -} - -scsi_play_audio_long( - target_info_t *tgt, - unsigned int start, - unsigned int len, - boolean_t relative_address, - io_req_t ior) -{ - scsi_cmd_play_audio_l_t *cmd; - - cmd = (scsi_cmd_play_audio_l_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_PLAY_AUDIO_LONG; - cmd->scsi_cmd_lun_and_relbit = relative_address ? SCSI_RELADR : 0; - cmd->scsi_cmd_lba1 = start >> 24; - cmd->scsi_cmd_lba2 = start >> 16; - cmd->scsi_cmd_lba3 = start >> 8; - cmd->scsi_cmd_lba4 = start >> 0; - cmd->scsi_cmd_xfer_len_1 = len >> 24; - cmd->scsi_cmd_xfer_len_2 = len >> 16; - cmd->scsi_cmd_xfer_len_3 = len >> 8; - cmd->scsi_cmd_xfer_len_4 = len >> 0; - cmd->scsi_cmd_xxx1 = 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_PLAY_AUDIO_LONG; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - - return tgt->done; -} - -scsi_play_audio_msf( - target_info_t *tgt, - int sm, - int ss, - int sf, - int em, - int es, - int ef, - io_req_t ior) -{ - scsi_cmd_play_audio_msf_t *cmd; - - cmd = (scsi_cmd_play_audio_msf_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_PLAY_AUDIO_MSF; - cmd->scsi_cmd_lun_and_relbit = 0; - cmd->scsi_cmd_lba1 = 0; - cmd->scsi_cmd_pamsf_startM = sm; - cmd->scsi_cmd_pamsf_startS = ss; - cmd->scsi_cmd_pamsf_startF = sf; - cmd->scsi_cmd_pamsf_endM = em; - cmd->scsi_cmd_pamsf_endS = es; - cmd->scsi_cmd_pamsf_endF = ef; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_PLAY_AUDIO_MSF; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - - return tgt->done; -} - -scsi_play_audio_track_index( - target_info_t *tgt, - int st, - int si, - int et, - int ei, - io_req_t ior) -{ - scsi_cmd_play_audio_ti_t *cmd; - - cmd = (scsi_cmd_play_audio_ti_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_PLAY_AUDIO_TI; - cmd->scsi_cmd_lun_and_relbit = 0; - cmd->scsi_cmd_lba1 = 0; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_pati_startT = st; - cmd->scsi_cmd_pati_startI = si; - cmd->scsi_cmd_xxx = 0; - cmd->scsi_cmd_pati_endT = et; - cmd->scsi_cmd_pati_endI = ei; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_PLAY_AUDIO_TI; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - - return tgt->done; -} - -scsi_play_audio_track_relative( - target_info_t *tgt, - unsigned int lba, - int st, - unsigned int len, - io_req_t ior) -{ - scsi_cmd_play_audio_tr_t *cmd; - - cmd = (scsi_cmd_play_audio_tr_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_PLAY_AUDIO_TR; - cmd->scsi_cmd_lun_and_relbit = 0; - cmd->scsi_cmd_lba1 = lba >> 24; - cmd->scsi_cmd_lba2 = lba >> 16; - cmd->scsi_cmd_lba3 = lba >> 8; - cmd->scsi_cmd_lba4 = lba >> 0; - cmd->scsi_cmd_patr_startT = st; - cmd->scsi_cmd_xfer_len_1 = len >> 8; - cmd->scsi_cmd_xfer_len_2 = len >> 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_PLAY_AUDIO_TR; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - - return tgt->done; -} - -scsi_play_audio_track_relative_long( - target_info_t *tgt, - unsigned int lba, - int st, - unsigned int len, - io_req_t ior) -{ - scsi_cmd_play_audio_tr_l_t *cmd; - - cmd = (scsi_cmd_play_audio_tr_l_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_PLAY_AUDIO_TR_LONG; - cmd->scsi_cmd_lun_and_relbit = 0; - cmd->scsi_cmd_lba1 = lba >> 24; - cmd->scsi_cmd_lba2 = lba >> 16; - cmd->scsi_cmd_lba3 = lba >> 8; - cmd->scsi_cmd_lba4 = lba >> 0; - cmd->scsi_cmd_xfer_len_1 = len >> 24; - cmd->scsi_cmd_xfer_len_2 = len >> 16; - cmd->scsi_cmd_xfer_len_3 = len >> 8; - cmd->scsi_cmd_xfer_len_4 = len >> 0; - cmd->scsi_cmd_patrl_startT = st; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_PLAY_AUDIO_TR_LONG; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - - return tgt->done; -} - -scsi_read_header( - target_info_t *tgt, - boolean_t msf_format, - unsigned int lba, - unsigned int allocsize, - io_req_t ior) -{ - scsi_cmd_read_header_t *cmd; - - cmd = (scsi_cmd_read_header_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_READ_HEADER; - cmd->scsi_cmd_lun_and_relbit = msf_format ? SCSI_CMD_CD_MSF : 0; - cmd->scsi_cmd_lba1 = lba >> 24; - cmd->scsi_cmd_lba2 = lba >> 16; - cmd->scsi_cmd_lba3 = lba >> 8; - cmd->scsi_cmd_lba4 = lba >> 0; - cmd->scsi_cmd_xxx = 0; - cmd->scsi_cmd_xfer_len_1 = allocsize >> 8; - cmd->scsi_cmd_xfer_len_2 = allocsize >> 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_READ_HEADER; - - scsi_go_and_wait(tgt, sizeof(*cmd), allocsize, ior); - - return tgt->done; -} - -scsi_read_subchannel( - target_info_t *tgt, - boolean_t msf_format, - unsigned int data_format, - unsigned int trackno, - io_req_t ior) -{ - scsi_cmd_read_subch_t *cmd; - int allocsize; - - switch (data_format) { - case SCSI_CMD_RS_FMT_SUBQ: - allocsize = sizeof(cdrom_chan_data_t); - trackno = 0; break; - case SCSI_CMD_RS_FMT_CURPOS: - allocsize = sizeof(cdrom_chan_curpos_t); - trackno = 0; break; - case SCSI_CMD_RS_FMT_CATALOG: - allocsize = sizeof(cdrom_chan_catalog_t); - trackno = 0; break; - case SCSI_CMD_RS_FMT_ISRC: - allocsize = sizeof(cdrom_chan_isrc_t); break; - } - - cmd = (scsi_cmd_read_subch_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_READ_SUBCH; - cmd->scsi_cmd_lun_and_relbit = msf_format ? SCSI_CMD_CD_MSF : 0; - cmd->scsi_cmd_lba1 = SCSI_CMD_RS_SUBQ; - cmd->scsi_cmd_rs_format = data_format; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_lba4 = 0; - cmd->scsi_cmd_rs_trackno = trackno; - cmd->scsi_cmd_xfer_len_1 = allocsize >> 8; - cmd->scsi_cmd_xfer_len_2 = allocsize >> 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_READ_SUBCH; - - scsi_go_and_wait(tgt, sizeof(*cmd), allocsize, ior); - - return tgt->done; -} - -scsi_read_toc( - target_info_t *tgt, - boolean_t msf_format, - int trackno, - int allocsize, - io_req_t ior) -{ - scsi_cmd_read_toc_t *cmd; - - cmd = (scsi_cmd_read_toc_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_READ_TOC; - cmd->scsi_cmd_lun_and_relbit = msf_format ? SCSI_CMD_CD_MSF : 0; - cmd->scsi_cmd_lba1 = 0; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_lba4 = 0; - cmd->scsi_cmd_rtoc_startT = trackno; - cmd->scsi_cmd_xfer_len_1 = allocsize >> 8; - cmd->scsi_cmd_xfer_len_2 = allocsize >> 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_READ_TOC; - - scsi_go_and_wait(tgt, sizeof(*cmd), allocsize, ior); - - return tgt->done; -} - -/* move elsewhere ifworks */ -scsi2_mode_select( - target_info_t *tgt, - boolean_t save, - unsigned char *page, - int pagesize, - io_req_t ior) -{ - scsi_cmd_mode_select_t *cmd; - scsi2_mode_param_t *parm; - - bzero(tgt->cmd_ptr, sizeof(*cmd) + sizeof(*parm)); - cmd = (scsi_cmd_mode_select_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_MODE_SELECT; - cmd->scsi_cmd_lun_and_lba1 = SCSI_CMD_MSL_PF | (save ? SCSI_CMD_MSL_SP : 0); - cmd->scsi_cmd_xfer_len = pagesize; - - parm = (scsi2_mode_param_t*) (cmd + 1); - - bcopy(page, parm, pagesize); - - tgt->cur_cmd = SCSI_CMD_MODE_SELECT; - - scsi_go_and_wait(tgt, sizeof(*cmd) + pagesize, 0, ior); - - return tgt->done; -} - -/* - * obnoxious - */ -cdrom_vendor_specific( - target_info_t *tgt, - scsi_command_group_2 *cmd, - unsigned char *params, - int paramlen, - int retlen, - io_req_t ior) -{ - bcopy(cmd, tgt->cmd_ptr, sizeof(*cmd)); - if (paramlen) - bcopy(params, tgt->cmd_ptr + sizeof(*cmd), paramlen); - - tgt->cur_cmd = cmd->scsi_cmd_code; - - scsi_go_and_wait(tgt, sizeof(*cmd) + paramlen, retlen, ior); - - return tgt->done; -} -#endif /* NSCSI > 0 */ diff --git a/scsi/scsi_scanner.c b/scsi/scsi_scanner.c deleted file mode 100644 index b6ba358..0000000 --- a/scsi/scsi_scanner.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_scanner.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Middle layer of the SCSI driver: SCSI protocol implementation - * - * This file contains code for SCSI commands for SCANNER devices. - */ - -#include <scsi.h> -#if (NSCSI > 0) - -#include <mach/std_types.h> - -char *scscn_name(internal) - boolean_t internal; -{ - return internal ? "oz" : "scanner"; -} - -#if 0 -scsi_get_buffer_status -scsi_get_window -scsi_object_position -scsi_scan -scsi_set_window -#endif -#endif /* NSCSI > 0 */ diff --git a/scsi/scsi_tape.c b/scsi/scsi_tape.c deleted file mode 100644 index c73f432..0000000 --- a/scsi/scsi_tape.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_tape.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Middle layer of the SCSI driver: SCSI protocol implementation - * - * This file contains code for SCSI commands for SEQUENTIAL ACCESS devices. - */ - -#include <mach/std_types.h> -#include <scsi/compat_30.h> - -#include <scsi/scsi.h> -#include <scsi/scsi_defs.h> - -#if (NSCSI > 0) - - -char *sctape_name(internal) - boolean_t internal; -{ - return internal ? "tz" : "tape"; -} - -void sctape_optimize(tgt) - target_info_t *tgt; -{ - register int i; - char result[6]; - - /* Some (DEC) tapes want to send you the self-test results */ - for (i = 0; i < 10; i++) { - if (scsi_receive_diag( tgt, result, sizeof(result), 0) - == SCSI_RET_SUCCESS) - break; - } - if (scsi_debug) - printf("[tape_rcvdiag: after %d, x%x x%x x%x x%x x%x x%x]\n", i+1, - result[0], result[1], result[2], result[3], result[4], result[5]); -} - -/* - * SCSI commands specific to sequential access devices - */ -int sctape_mode_select( tgt, vuque_data, vuque_data_len, newspeed, ior) - register target_info_t *tgt; - unsigned char *vuque_data; - int vuque_data_len; - int newspeed; - io_req_t ior; -{ - scsi_cmd_mode_select_t *cmd; - scsi_mode_select_param_t *parm; - - bzero(tgt->cmd_ptr, sizeof(*cmd) + 2 * sizeof(*parm)); - cmd = (scsi_cmd_mode_select_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_MODE_SELECT; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_xfer_len = sizeof(scsi_mode_select_param_t) + vuque_data_len; - - parm = (scsi_mode_select_param_t*) (cmd + 1); - if (newspeed) { - parm->speed = tgt->dev_info.tape.speed; - } else { - /* Standard sez 0 -> no change */ - parm->speed = 0; - } - /* parm->medium_type = 0; reserved */ - parm->descs[0].density_code = tgt->dev_info.tape.density; - parm->buffer_mode = 1; - parm->desc_len = 8; - if (tgt->dev_info.tape.fixed_size) { - register int reclen = tgt->block_size; - parm->descs[0].reclen1 = reclen >> 16; - parm->descs[0].reclen2 = reclen >> 8; - parm->descs[0].reclen3 = reclen; - } - - if (vuque_data_len) - bcopy(vuque_data, (char*)(parm+1), vuque_data_len); - - tgt->cur_cmd = SCSI_CMD_MODE_SELECT; - - scsi_go_and_wait(tgt, sizeof(*cmd) + sizeof(*parm) + vuque_data_len, 0, ior); - - return tgt->done; -} - -void sctape_read( tgt, ior) - register target_info_t *tgt; - io_req_t ior; -{ - scsi_cmd_read_t *cmd; - register unsigned len, max; -# define nbytes max - boolean_t fixed = FALSE; - - max = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - - len = ior->io_count; - if (tgt->dev_info.tape.fixed_size) { - unsigned int bs = tgt->block_size; - fixed = TRUE; - nbytes = len; - ior->io_residual += len % bs; - len = len / bs; - } else { - if (max > tgt->dev_info.tape.maxreclen) - max = tgt->dev_info.tape.maxreclen; - if (len > max) { - ior->io_residual = len - max; - len = max; - } - if (len < tgt->block_size) - len = tgt->block_size; - nbytes = len; - } - - cmd = (scsi_cmd_read_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_READ; - cmd->scsi_cmd_lun_and_lba1 = fixed ? SCSI_CMD_TP_FIXED : 0; - cmd->scsi_cmd_lba2 = len >> 16; - cmd->scsi_cmd_lba3 = len >> 8; - cmd->scsi_cmd_xfer_len = len; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_READ; - - scsi_go(tgt, sizeof(*cmd), nbytes, FALSE); -#undef nbytes -} - -void sctape_write( tgt, ior) - register target_info_t *tgt; - io_req_t ior; -{ - scsi_cmd_write_t *cmd; - register unsigned len, max; - boolean_t fixed = FALSE; - - len = ior->io_count; - max = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - - if (tgt->dev_info.tape.fixed_size) { - unsigned int bs = tgt->block_size; - fixed = TRUE; - ior->io_residual += len % bs; - len = len / bs; - } else { - if (max > tgt->dev_info.tape.maxreclen) - max = tgt->dev_info.tape.maxreclen; - if (len > max) { - ior->io_residual = len - max; - len = max; - } - if (len < tgt->block_size) - len = tgt->block_size; - } - - cmd = (scsi_cmd_write_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_WRITE; - cmd->scsi_cmd_lun_and_lba1 = fixed ? SCSI_CMD_TP_FIXED : 0; - cmd->scsi_cmd_lba2 = len >> 16; - cmd->scsi_cmd_lba3 = len >> 8; - cmd->scsi_cmd_xfer_len = len; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_WRITE; - - scsi_go(tgt, sizeof(*cmd), 0, FALSE); -} - -int scsi_rewind( tgt, ior, wait) - register target_info_t *tgt; - io_req_t ior; - boolean_t wait; -{ - scsi_cmd_rewind_t *cmd; - - - cmd = (scsi_cmd_rewind_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_REWIND; - cmd->scsi_cmd_lun_and_lba1 = wait ? 0 : SCSI_CMD_REW_IMMED; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_xfer_len = 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_REWIND; - - scsi_go( tgt, sizeof(*cmd), 0, FALSE); - return SCSI_RET_SUCCESS; -} - -int scsi_write_filemarks( tgt, count, ior) - register target_info_t *tgt; - register unsigned int count; - io_req_t ior; -{ - scsi_cmd_write_fil_t *cmd; - - cmd = (scsi_cmd_write_fil_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_WRITE_FILEMARKS; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba2 = count >> 16; - cmd->scsi_cmd_lba3 = count >> 8; - cmd->scsi_cmd_xfer_len = count; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - - tgt->cur_cmd = SCSI_CMD_WRITE_FILEMARKS; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - - return tgt->done; -} - -int scsi_space( tgt, mode, count, ior) - register target_info_t *tgt; - int mode; - register int count; - io_req_t ior; -{ - scsi_cmd_space_t *cmd; - - cmd = (scsi_cmd_space_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_SPACE; - cmd->scsi_cmd_lun_and_lba1 = mode & 0x3; - cmd->scsi_cmd_lba2 = count >> 16; - cmd->scsi_cmd_lba3 = count >> 8; - cmd->scsi_cmd_xfer_len = count; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - - tgt->cur_cmd = SCSI_CMD_SPACE; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); - - return tgt->done; -} - - -int scsi_read_block_limits( tgt, ior) - register target_info_t *tgt; - io_req_t ior; -{ - scsi_cmd_block_limits_t *cmd; - - cmd = (scsi_cmd_block_limits_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_READ_BLOCK_LIMITS; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_xfer_len = 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - - tgt->cur_cmd = SCSI_CMD_READ_BLOCK_LIMITS; - - scsi_go_and_wait(tgt, sizeof(*cmd), sizeof(scsi_blimits_data_t), ior); - return tgt->done; -} - -#if 0 /* unused */ - -void scsi_track_select( tgt, trackno, ior) - register target_info_t *tgt; - register unsigned char trackno; - io_req_t ior; -{ - scsi_cmd_seek_t *cmd; - - cmd = (scsi_cmd_seek_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_TRACK_SELECT; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_tp_trackno = trackno; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - - tgt->cur_cmd = SCSI_CMD_TRACK_SELECT; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); -} - -void scsi_read_reverse( tgt, ior) - register target_info_t *tgt; - io_req_t ior; -{ - scsi_cmd_rev_read_t *cmd; - register unsigned len; - unsigned int max_dma_data; - - max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - - len = ior->io_count; - if (len > max_dma_data) - len = max_dma_data; - - cmd = (scsi_cmd_rev_read_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_READ_REVERSE; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba2 = len >> 16; - cmd->scsi_cmd_lba3 = len >> 8; - cmd->scsi_cmd_xfer_len = len; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_READ_REVERSE; - - scsi_go(tgt, sizeof(*cmd), len, FALSE); -} - -void sctape_verify( tgt, len, ior) - register target_info_t *tgt; - register unsigned int len; - io_req_t ior; -{ - scsi_cmd_verify_t *cmd; - - cmd = (scsi_cmd_verify_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_VERIFY_0; - cmd->scsi_cmd_lun_and_lba1 = 0;/* XXX */ - cmd->scsi_cmd_lba2 = len >> 16; - cmd->scsi_cmd_lba3 = len >> 8; - cmd->scsi_cmd_xfer_len = len; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - - tgt->cur_cmd = SCSI_CMD_VERIFY_0; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); -} - - -void scsi_recover_buffered_data( tgt, ior) - register target_info_t *tgt; - io_req_t ior; -{ - scsi_cmd_recover_buffer_t *cmd; - register unsigned len; - unsigned int max_dma_data; - - max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data; - - len = ior->io_count; - if (len > max_dma_data) - len = max_dma_data; - - cmd = (scsi_cmd_recover_buffer_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_RECOVER_BUFFERED_DATA; - cmd->scsi_cmd_lun_and_lba1 = 0; - cmd->scsi_cmd_lba2 = len >> 16; - cmd->scsi_cmd_lba3 = len >> 8; - cmd->scsi_cmd_xfer_len = len; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - tgt->cur_cmd = SCSI_CMD_RECOVER_BUFFERED_DATA; - - scsi_go(tgt, sizeof(*cmd), len, FALSE); -} - -void scsi_erase( tgt, mode, ior) - register target_info_t *tgt; - io_req_t ior; -{ - scsi_cmd_erase_t *cmd; - - cmd = (scsi_cmd_erase_t*) (tgt->cmd_ptr); - cmd->scsi_cmd_code = SCSI_CMD_ERASE; - cmd->scsi_cmd_lun_and_lba1 = mode & SCSI_CMD_ER_LONG; - cmd->scsi_cmd_lba2 = 0; - cmd->scsi_cmd_lba3 = 0; - cmd->scsi_cmd_xfer_len = 0; - cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ - - - tgt->cur_cmd = SCSI_CMD_ERASE; - - scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior); -} - -#endif - -#ifdef SCSI2 -scsi_locate -scsi_read_position -#endif SCSI2 -#endif /* NSCSI > 0 */ diff --git a/scsi/scsi_worm.c b/scsi/scsi_worm.c deleted file mode 100644 index 7490ea2..0000000 --- a/scsi/scsi_worm.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scsi_worm.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 10/90 - * - * Middle layer of the SCSI driver: SCSI protocol implementation - * - * This file contains code for SCSI commands for WORM devices, - * e.g. disks that employ write once / read multiple media. - */ - -#include <mach/std_types.h> - - - -char *scworm_name(internal) - boolean_t internal; -{ - return internal ? "rz" : "WORM-disk"; -} - -#ifdef SCSI2 -see optical mem: - - no format - - no "update" -#endif SCSI2 |