diff options
Diffstat (limited to 'drivers/scsi/aic7xxx/aic7770_osm.c')
-rw-r--r-- | drivers/scsi/aic7xxx/aic7770_osm.c | 175 |
1 files changed, 63 insertions, 112 deletions
diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c index d0e9b54ab008..d4ed5e9f830a 100644 --- a/drivers/scsi/aic7xxx/aic7770_osm.c +++ b/drivers/scsi/aic7xxx/aic7770_osm.c | |||
@@ -44,109 +44,6 @@ | |||
44 | #include <linux/device.h> | 44 | #include <linux/device.h> |
45 | #include <linux/eisa.h> | 45 | #include <linux/eisa.h> |
46 | 46 | ||
47 | #define EISA_MFCTR_CHAR0(ID) (char)(((ID>>26) & 0x1F) | '@') /* Bits 26-30 */ | ||
48 | #define EISA_MFCTR_CHAR1(ID) (char)(((ID>>21) & 0x1F) | '@') /* Bits 21-25 */ | ||
49 | #define EISA_MFCTR_CHAR2(ID) (char)(((ID>>16) & 0x1F) | '@') /* Bits 16-20 */ | ||
50 | #define EISA_PRODUCT_ID(ID) (short)((ID>>4) & 0xFFF) /* Bits 4-15 */ | ||
51 | #define EISA_REVISION_ID(ID) (uint8_t)(ID & 0x0F) /* Bits 0-3 */ | ||
52 | |||
53 | static int aic7770_eisa_dev_probe(struct device *dev); | ||
54 | static int aic7770_eisa_dev_remove(struct device *dev); | ||
55 | static struct eisa_driver aic7770_driver = { | ||
56 | .driver = { | ||
57 | .name = "aic7xxx", | ||
58 | .probe = aic7770_eisa_dev_probe, | ||
59 | .remove = aic7770_eisa_dev_remove, | ||
60 | } | ||
61 | }; | ||
62 | |||
63 | typedef struct device *aic7770_dev_t; | ||
64 | |||
65 | static int aic7770_linux_config(struct aic7770_identity *entry, | ||
66 | aic7770_dev_t dev, u_int eisaBase); | ||
67 | |||
68 | int | ||
69 | ahc_linux_eisa_init(void) | ||
70 | { | ||
71 | struct eisa_device_id *eid; | ||
72 | struct aic7770_identity *id; | ||
73 | int i; | ||
74 | |||
75 | if (aic7xxx_probe_eisa_vl == 0) | ||
76 | return -ENODEV; | ||
77 | |||
78 | /* | ||
79 | * Linux requires the EISA IDs to be specified in | ||
80 | * the EISA ID string format. Perform the conversion | ||
81 | * and setup a table with a NUL terminal entry. | ||
82 | */ | ||
83 | aic7770_driver.id_table = malloc(sizeof(struct eisa_device_id) * | ||
84 | (ahc_num_aic7770_devs + 1), | ||
85 | M_DEVBUF, M_NOWAIT); | ||
86 | if (aic7770_driver.id_table == NULL) | ||
87 | return -ENOMEM; | ||
88 | |||
89 | for (eid = (struct eisa_device_id *)aic7770_driver.id_table, | ||
90 | id = aic7770_ident_table, i = 0; | ||
91 | i < ahc_num_aic7770_devs; eid++, id++, i++) { | ||
92 | |||
93 | sprintf(eid->sig, "%c%c%c%03X%01X", | ||
94 | EISA_MFCTR_CHAR0(id->full_id), | ||
95 | EISA_MFCTR_CHAR1(id->full_id), | ||
96 | EISA_MFCTR_CHAR2(id->full_id), | ||
97 | EISA_PRODUCT_ID(id->full_id), | ||
98 | EISA_REVISION_ID(id->full_id)); | ||
99 | eid->driver_data = i; | ||
100 | } | ||
101 | eid->sig[0] = 0; | ||
102 | |||
103 | return eisa_driver_register(&aic7770_driver); | ||
104 | } | ||
105 | |||
106 | void | ||
107 | ahc_linux_eisa_exit(void) | ||
108 | { | ||
109 | if(aic7xxx_probe_eisa_vl != 0 && aic7770_driver.id_table != NULL) { | ||
110 | eisa_driver_unregister(&aic7770_driver); | ||
111 | free(aic7770_driver.id_table, M_DEVBUF); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | static int | ||
116 | aic7770_linux_config(struct aic7770_identity *entry, aic7770_dev_t dev, | ||
117 | u_int eisaBase) | ||
118 | { | ||
119 | struct ahc_softc *ahc; | ||
120 | char buf[80]; | ||
121 | char *name; | ||
122 | int error; | ||
123 | |||
124 | /* | ||
125 | * Allocate a softc for this card and | ||
126 | * set it up for attachment by our | ||
127 | * common detect routine. | ||
128 | */ | ||
129 | sprintf(buf, "ahc_eisa:%d", eisaBase >> 12); | ||
130 | name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); | ||
131 | if (name == NULL) | ||
132 | return (ENOMEM); | ||
133 | strcpy(name, buf); | ||
134 | ahc = ahc_alloc(&aic7xxx_driver_template, name); | ||
135 | if (ahc == NULL) | ||
136 | return (ENOMEM); | ||
137 | error = aic7770_config(ahc, entry, eisaBase); | ||
138 | if (error != 0) { | ||
139 | ahc->bsh.ioport = 0; | ||
140 | ahc_free(ahc); | ||
141 | return (error); | ||
142 | } | ||
143 | |||
144 | dev->driver_data = (void *)ahc; | ||
145 | if (aic7xxx_detect_complete) | ||
146 | error = ahc_linux_register_host(ahc, &aic7xxx_driver_template); | ||
147 | return (error); | ||
148 | } | ||
149 | |||
150 | int | 47 | int |
151 | aic7770_map_registers(struct ahc_softc *ahc, u_int port) | 48 | aic7770_map_registers(struct ahc_softc *ahc, u_int port) |
152 | { | 49 | { |
@@ -178,25 +75,79 @@ aic7770_map_int(struct ahc_softc *ahc, u_int irq) | |||
178 | } | 75 | } |
179 | 76 | ||
180 | static int | 77 | static int |
181 | aic7770_eisa_dev_probe(struct device *dev) | 78 | aic7770_probe(struct device *dev) |
182 | { | 79 | { |
183 | struct eisa_device *edev; | 80 | struct eisa_device *edev = to_eisa_device(dev); |
81 | u_int eisaBase = edev->base_addr+AHC_EISA_SLOT_OFFSET; | ||
82 | struct ahc_softc *ahc; | ||
83 | char buf[80]; | ||
84 | char *name; | ||
85 | int error; | ||
86 | |||
87 | sprintf(buf, "ahc_eisa:%d", eisaBase >> 12); | ||
88 | name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); | ||
89 | if (name == NULL) | ||
90 | return (ENOMEM); | ||
91 | strcpy(name, buf); | ||
92 | ahc = ahc_alloc(&aic7xxx_driver_template, name); | ||
93 | if (ahc == NULL) | ||
94 | return (ENOMEM); | ||
95 | error = aic7770_config(ahc, aic7770_ident_table + edev->id.driver_data, | ||
96 | eisaBase); | ||
97 | if (error != 0) { | ||
98 | ahc->bsh.ioport = 0; | ||
99 | ahc_free(ahc); | ||
100 | return (error); | ||
101 | } | ||
102 | |||
103 | dev_set_drvdata(dev, ahc); | ||
184 | 104 | ||
185 | edev = to_eisa_device(dev); | 105 | if (aic7xxx_detect_complete) |
186 | return (aic7770_linux_config(aic7770_ident_table + edev->id.driver_data, | 106 | error = ahc_linux_register_host(ahc, &aic7xxx_driver_template); |
187 | dev, edev->base_addr+AHC_EISA_SLOT_OFFSET)); | 107 | return (error); |
188 | } | 108 | } |
189 | 109 | ||
190 | static int | 110 | static int |
191 | aic7770_eisa_dev_remove(struct device *dev) | 111 | aic7770_remove(struct device *dev) |
192 | { | 112 | { |
193 | struct ahc_softc *ahc = dev_get_drvata(dev); | 113 | struct ahc_softc *ahc = dev_get_drvdata(dev); |
194 | u_long s; | 114 | u_long s; |
195 | 115 | ||
196 | ahc_lock(ahc, &s); | 116 | ahc_lock(ahc, &s); |
197 | ahc_intr_enable(ahc, FALSE); | 117 | ahc_intr_enable(ahc, FALSE); |
198 | ahc_unlock(ahc, &s); | 118 | ahc_unlock(ahc, &s); |
199 | ahc_free(ahc); | ||
200 | 119 | ||
201 | return (0); | 120 | ahc_free(ahc); |
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static struct eisa_device_id aic7770_ids[] = { | ||
125 | { "ADP7771", 0 }, /* AHA 274x */ | ||
126 | { "ADP7756", 1 }, /* AHA 284x BIOS enabled */ | ||
127 | { "ADP7757", 2 }, /* AHA 284x BIOS disabled */ | ||
128 | { "ADP7782", 3 }, /* AHA 274x Olivetti OEM */ | ||
129 | { "ADP7783", 4 }, /* AHA 274x Olivetti OEM (Differential) */ | ||
130 | { "ADP7770", 5 }, /* AIC7770 generic */ | ||
131 | { "" } | ||
132 | }; | ||
133 | |||
134 | static struct eisa_driver aic7770_driver = { | ||
135 | .id_table = aic7770_ids, | ||
136 | .driver = { | ||
137 | .name = "aic7xxx", | ||
138 | .probe = aic7770_probe, | ||
139 | .remove = aic7770_remove, | ||
140 | } | ||
141 | }; | ||
142 | |||
143 | int | ||
144 | ahc_linux_eisa_init(void) | ||
145 | { | ||
146 | return eisa_driver_register(&aic7770_driver); | ||
147 | } | ||
148 | |||
149 | void | ||
150 | ahc_linux_eisa_exit(void) | ||
151 | { | ||
152 | eisa_driver_unregister(&aic7770_driver); | ||
202 | } | 153 | } |