1 |
1626 |
jcastillo |
/*
|
2 |
|
|
|
3 |
|
|
Linux Driver for Mylex DAC960 PCI RAID Controllers
|
4 |
|
|
|
5 |
|
|
Copyright 1998 by Leonard N. Zubkoff <lnz@dandelion.com>
|
6 |
|
|
|
7 |
|
|
This program is free software; you may redistribute and/or modify it under
|
8 |
|
|
the terms of the GNU General Public License Version 2 as published by the
|
9 |
|
|
Free Software Foundation.
|
10 |
|
|
|
11 |
|
|
This program is distributed in the hope that it will be useful, but
|
12 |
|
|
WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
|
13 |
|
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
14 |
|
|
for complete details.
|
15 |
|
|
|
16 |
|
|
The author respectfully requests that any modifications to this software be
|
17 |
|
|
sent directly to him for evaluation and testing.
|
18 |
|
|
|
19 |
|
|
*/
|
20 |
|
|
|
21 |
|
|
|
22 |
|
|
#define DAC960_DriverVersion "2.0.0 Beta3"
|
23 |
|
|
#define DAC960_DriverDate "29 November 1998"
|
24 |
|
|
|
25 |
|
|
|
26 |
|
|
#include <linux/version.h>
|
27 |
|
|
#include <linux/module.h>
|
28 |
|
|
#include <linux/types.h>
|
29 |
|
|
#include <linux/blkdev.h>
|
30 |
|
|
#include <linux/delay.h>
|
31 |
|
|
#include <linux/hdreg.h>
|
32 |
|
|
#include <linux/ioport.h>
|
33 |
|
|
#include <linux/locks.h>
|
34 |
|
|
#include <linux/mm.h>
|
35 |
|
|
#include <linux/malloc.h>
|
36 |
|
|
#include <linux/timer.h>
|
37 |
|
|
#include <linux/pci.h>
|
38 |
|
|
#include <linux/bios32.h>
|
39 |
|
|
#include <asm/io.h>
|
40 |
|
|
#include <asm/irq.h>
|
41 |
|
|
#include <asm/segment.h>
|
42 |
|
|
#include "DAC960.h"
|
43 |
|
|
|
44 |
|
|
|
45 |
|
|
/*
|
46 |
|
|
DAC960_ControllerCount is the number of DAC960 Controllers.
|
47 |
|
|
*/
|
48 |
|
|
|
49 |
|
|
static int
|
50 |
|
|
DAC960_ControllerCount = 0;
|
51 |
|
|
|
52 |
|
|
|
53 |
|
|
/*
|
54 |
|
|
DAC960_Controllers is an array of pointers to the DAC960 Controller
|
55 |
|
|
structures.
|
56 |
|
|
*/
|
57 |
|
|
|
58 |
|
|
static DAC960_Controller_T
|
59 |
|
|
*DAC960_Controllers[DAC960_MaxControllers] = { NULL };
|
60 |
|
|
|
61 |
|
|
|
62 |
|
|
/*
|
63 |
|
|
DAC960_FileOperations is the File Operations structure for DAC960 Logical
|
64 |
|
|
Disk Devices.
|
65 |
|
|
*/
|
66 |
|
|
|
67 |
|
|
static FileOperations_T
|
68 |
|
|
DAC960_FileOperations =
|
69 |
|
|
{ lseek: NULL,
|
70 |
|
|
read: block_read,
|
71 |
|
|
write: block_write,
|
72 |
|
|
readdir: NULL,
|
73 |
|
|
select: NULL,
|
74 |
|
|
ioctl: DAC960_Ioctl,
|
75 |
|
|
mmap: NULL,
|
76 |
|
|
open: DAC960_Open,
|
77 |
|
|
release: DAC960_Release,
|
78 |
|
|
fsync: block_fsync,
|
79 |
|
|
fasync: NULL,
|
80 |
|
|
check_media_change: NULL,
|
81 |
|
|
revalidate: NULL };
|
82 |
|
|
|
83 |
|
|
|
84 |
|
|
/*
|
85 |
|
|
DAC960_AnnounceDriver announces the Driver Version and Date, Author's Name,
|
86 |
|
|
Copyright Notice, and Electronic Mail Address.
|
87 |
|
|
*/
|
88 |
|
|
|
89 |
|
|
static void DAC960_AnnounceDriver(DAC960_Controller_T *Controller)
|
90 |
|
|
{
|
91 |
|
|
DAC960_Announce("***** DAC960 RAID Driver Version "
|
92 |
|
|
DAC960_DriverVersion " of "
|
93 |
|
|
DAC960_DriverDate " *****\n", Controller);
|
94 |
|
|
DAC960_Announce("Copyright 1998 by Leonard N. Zubkoff "
|
95 |
|
|
"<lnz@dandelion.com>\n", Controller);
|
96 |
|
|
}
|
97 |
|
|
|
98 |
|
|
|
99 |
|
|
/*
|
100 |
|
|
DAC960_Failure prints a standardized error message, and then returns false.
|
101 |
|
|
*/
|
102 |
|
|
|
103 |
|
|
static boolean DAC960_Failure(DAC960_Controller_T *Controller,
|
104 |
|
|
char *ErrorMessage)
|
105 |
|
|
{
|
106 |
|
|
DAC960_Error("While configuring DAC960 PCI RAID Controller at\n",
|
107 |
|
|
Controller);
|
108 |
|
|
if (Controller->IO_Address == 0)
|
109 |
|
|
DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A "
|
110 |
|
|
"PCI Address 0x%X\n", Controller,
|
111 |
|
|
Controller->Bus, Controller->Device,
|
112 |
|
|
Controller->Function, Controller->PCI_Address);
|
113 |
|
|
else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "
|
114 |
|
|
"0x%X PCI Address 0x%X\n", Controller,
|
115 |
|
|
Controller->Bus, Controller->Device,
|
116 |
|
|
Controller->Function, Controller->IO_Address,
|
117 |
|
|
Controller->PCI_Address);
|
118 |
|
|
DAC960_Error("%s FAILED - DETACHING\n", Controller, ErrorMessage);
|
119 |
|
|
return false;
|
120 |
|
|
}
|
121 |
|
|
|
122 |
|
|
|
123 |
|
|
/*
|
124 |
|
|
DAC960_ClearCommand clears critical fields of Command.
|
125 |
|
|
*/
|
126 |
|
|
|
127 |
|
|
static inline void DAC960_ClearCommand(DAC960_Command_T *Command)
|
128 |
|
|
{
|
129 |
|
|
DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
|
130 |
|
|
CommandMailbox->Words[0] = 0;
|
131 |
|
|
CommandMailbox->Words[1] = 0;
|
132 |
|
|
CommandMailbox->Words[2] = 0;
|
133 |
|
|
CommandMailbox->Words[3] = 0;
|
134 |
|
|
Command->CommandStatus = 0;
|
135 |
|
|
}
|
136 |
|
|
|
137 |
|
|
|
138 |
|
|
/*
|
139 |
|
|
DAC960_AllocateCommand allocates a Command structure from Controller's
|
140 |
|
|
free list.
|
141 |
|
|
*/
|
142 |
|
|
|
143 |
|
|
static inline DAC960_Command_T *DAC960_AllocateCommand(DAC960_Controller_T
|
144 |
|
|
*Controller)
|
145 |
|
|
{
|
146 |
|
|
DAC960_Command_T *Command = Controller->FreeCommands;
|
147 |
|
|
if (Command == NULL) return NULL;
|
148 |
|
|
Controller->FreeCommands = Command->Next;
|
149 |
|
|
Command->Next = NULL;
|
150 |
|
|
return Command;
|
151 |
|
|
}
|
152 |
|
|
|
153 |
|
|
|
154 |
|
|
/*
|
155 |
|
|
DAC960_DeallocateCommand deallocates Command, returning it to Controller's
|
156 |
|
|
free list.
|
157 |
|
|
*/
|
158 |
|
|
|
159 |
|
|
static inline void DAC960_DeallocateCommand(DAC960_Command_T *Command)
|
160 |
|
|
{
|
161 |
|
|
DAC960_Controller_T *Controller = Command->Controller;
|
162 |
|
|
Command->Next = Controller->FreeCommands;
|
163 |
|
|
Controller->FreeCommands = Command;
|
164 |
|
|
}
|
165 |
|
|
|
166 |
|
|
|
167 |
|
|
/*
|
168 |
|
|
DAC960_QueueCommand queues Command.
|
169 |
|
|
*/
|
170 |
|
|
|
171 |
|
|
static void DAC960_QueueCommand(DAC960_Command_T *Command)
|
172 |
|
|
{
|
173 |
|
|
DAC960_Controller_T *Controller = Command->Controller;
|
174 |
|
|
void *ControllerBaseAddress = Controller->BaseAddress;
|
175 |
|
|
DAC960_V4_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
|
176 |
|
|
DAC960_V4_CommandMailbox_T *NextCommandMailbox;
|
177 |
|
|
CommandMailbox->Common.CommandIdentifier = Command - Controller->Commands;
|
178 |
|
|
switch (Controller->ControllerType)
|
179 |
|
|
{
|
180 |
|
|
case DAC960_V4_Controller:
|
181 |
|
|
NextCommandMailbox = Controller->NextCommandMailbox;
|
182 |
|
|
DAC960_V4_WriteCommandMailbox(NextCommandMailbox, CommandMailbox);
|
183 |
|
|
if (Controller->PreviousCommandMailbox->Words[0] == 0)
|
184 |
|
|
DAC960_V4_NewCommand(ControllerBaseAddress);
|
185 |
|
|
Controller->PreviousCommandMailbox = NextCommandMailbox;
|
186 |
|
|
if (++NextCommandMailbox > Controller->LastCommandMailbox)
|
187 |
|
|
NextCommandMailbox = Controller->FirstCommandMailbox;
|
188 |
|
|
Controller->NextCommandMailbox = NextCommandMailbox;
|
189 |
|
|
break;
|
190 |
|
|
case DAC960_V3_Controller:
|
191 |
|
|
while (DAC960_V3_MailboxFullP(ControllerBaseAddress))
|
192 |
|
|
udelay(1);
|
193 |
|
|
DAC960_V3_WriteCommandMailbox(ControllerBaseAddress, CommandMailbox);
|
194 |
|
|
DAC960_V3_NewCommand(ControllerBaseAddress);
|
195 |
|
|
break;
|
196 |
|
|
}
|
197 |
|
|
}
|
198 |
|
|
|
199 |
|
|
|
200 |
|
|
/*
|
201 |
|
|
DAC960_ExecuteCommand executes Command and waits for completion. It
|
202 |
|
|
returns true on success and false on failure.
|
203 |
|
|
*/
|
204 |
|
|
|
205 |
|
|
static boolean DAC960_ExecuteCommand(DAC960_Command_T *Command)
|
206 |
|
|
{
|
207 |
|
|
Semaphore_T Semaphore = MUTEX_LOCKED;
|
208 |
|
|
Command->Semaphore = &Semaphore;
|
209 |
|
|
DAC960_QueueCommand(Command);
|
210 |
|
|
down(&Semaphore);
|
211 |
|
|
return Command->CommandStatus == DAC960_NormalCompletion;
|
212 |
|
|
}
|
213 |
|
|
|
214 |
|
|
|
215 |
|
|
/*
|
216 |
|
|
DAC960_ExecuteType3 executes a DAC960 Type 3 Command and waits for
|
217 |
|
|
completion. It returns true on success and false on failure.
|
218 |
|
|
*/
|
219 |
|
|
|
220 |
|
|
static boolean DAC960_ExecuteType3(DAC960_Controller_T *Controller,
|
221 |
|
|
DAC960_CommandOpcode_T CommandOpcode,
|
222 |
|
|
void *DataPointer)
|
223 |
|
|
{
|
224 |
|
|
DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
|
225 |
|
|
DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
|
226 |
|
|
boolean Result;
|
227 |
|
|
DAC960_ClearCommand(Command);
|
228 |
|
|
Command->CommandType = DAC960_ImmediateCommand;
|
229 |
|
|
CommandMailbox->Type3.CommandOpcode = CommandOpcode;
|
230 |
|
|
CommandMailbox->Type3.BusAddress = Virtual_to_Bus(DataPointer);
|
231 |
|
|
Result = DAC960_ExecuteCommand(Command);
|
232 |
|
|
DAC960_DeallocateCommand(Command);
|
233 |
|
|
return Result;
|
234 |
|
|
}
|
235 |
|
|
|
236 |
|
|
|
237 |
|
|
/*
|
238 |
|
|
DAC960_ExecuteType3D executes a DAC960 Type 3D Command and waits for
|
239 |
|
|
completion. It returns true on success and false on failure.
|
240 |
|
|
*/
|
241 |
|
|
|
242 |
|
|
static boolean DAC960_ExecuteType3D(DAC960_Controller_T *Controller,
|
243 |
|
|
DAC960_CommandOpcode_T CommandOpcode,
|
244 |
|
|
unsigned char Channel,
|
245 |
|
|
unsigned char TargetID,
|
246 |
|
|
void *DataPointer)
|
247 |
|
|
{
|
248 |
|
|
DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
|
249 |
|
|
DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
|
250 |
|
|
boolean Result;
|
251 |
|
|
DAC960_ClearCommand(Command);
|
252 |
|
|
Command->CommandType = DAC960_ImmediateCommand;
|
253 |
|
|
CommandMailbox->Type3D.CommandOpcode = CommandOpcode;
|
254 |
|
|
CommandMailbox->Type3D.Channel = Channel;
|
255 |
|
|
CommandMailbox->Type3D.TargetID = TargetID;
|
256 |
|
|
CommandMailbox->Type3D.BusAddress = Virtual_to_Bus(DataPointer);
|
257 |
|
|
Result = DAC960_ExecuteCommand(Command);
|
258 |
|
|
DAC960_DeallocateCommand(Command);
|
259 |
|
|
return Result;
|
260 |
|
|
}
|
261 |
|
|
|
262 |
|
|
|
263 |
|
|
/*
|
264 |
|
|
DAC960_V4_EnableMemoryMailboxInterface enables the V4 Memory Mailbox
|
265 |
|
|
Interface.
|
266 |
|
|
*/
|
267 |
|
|
|
268 |
|
|
static boolean DAC960_V4_EnableMemoryMailboxInterface(DAC960_Controller_T
|
269 |
|
|
*Controller)
|
270 |
|
|
{
|
271 |
|
|
void *ControllerBaseAddress = Controller->BaseAddress;
|
272 |
|
|
DAC960_V4_CommandMailbox_T *CommandMailboxesMemory;
|
273 |
|
|
DAC960_V4_StatusMailbox_T *StatusMailboxesMemory;
|
274 |
|
|
DAC960_CommandMailbox_T CommandMailbox;
|
275 |
|
|
DAC960_CommandStatus_T CommandStatus;
|
276 |
|
|
CommandMailboxesMemory =
|
277 |
|
|
(DAC960_V4_CommandMailbox_T *) __get_free_pages(GFP_KERNEL, 1, 0);
|
278 |
|
|
memset(CommandMailboxesMemory, 0, PAGE_SIZE << 1);
|
279 |
|
|
Controller->FirstCommandMailbox = CommandMailboxesMemory;
|
280 |
|
|
CommandMailboxesMemory += DAC960_CommandMailboxCount - 1;
|
281 |
|
|
Controller->LastCommandMailbox = CommandMailboxesMemory;
|
282 |
|
|
Controller->NextCommandMailbox = Controller->FirstCommandMailbox;
|
283 |
|
|
Controller->PreviousCommandMailbox = Controller->LastCommandMailbox;
|
284 |
|
|
StatusMailboxesMemory =
|
285 |
|
|
(DAC960_V4_StatusMailbox_T *) (CommandMailboxesMemory + 1);
|
286 |
|
|
Controller->FirstStatusMailbox = StatusMailboxesMemory;
|
287 |
|
|
StatusMailboxesMemory += DAC960_StatusMailboxCount - 1;
|
288 |
|
|
Controller->LastStatusMailbox = StatusMailboxesMemory;
|
289 |
|
|
Controller->NextStatusMailbox = Controller->FirstStatusMailbox;
|
290 |
|
|
/* Enable the Memory Mailbox Interface. */
|
291 |
|
|
CommandMailbox.TypeX.CommandOpcode = 0x2B;
|
292 |
|
|
CommandMailbox.TypeX.CommandIdentifier = 0;
|
293 |
|
|
CommandMailbox.TypeX.CommandOpcode2 = 0x10;
|
294 |
|
|
CommandMailbox.TypeX.CommandMailboxesBusAddress =
|
295 |
|
|
Virtual_to_Bus(Controller->FirstCommandMailbox);
|
296 |
|
|
CommandMailbox.TypeX.StatusMailboxesBusAddress =
|
297 |
|
|
Virtual_to_Bus(Controller->FirstStatusMailbox);
|
298 |
|
|
while (DAC960_V4_MailboxFullP(ControllerBaseAddress))
|
299 |
|
|
udelay(1);
|
300 |
|
|
DAC960_V4_WriteLegacyCommand(ControllerBaseAddress, &CommandMailbox);
|
301 |
|
|
DAC960_V4_NewCommand(ControllerBaseAddress);
|
302 |
|
|
while (!DAC960_V4_StatusAvailableP(ControllerBaseAddress))
|
303 |
|
|
udelay(1);
|
304 |
|
|
CommandStatus = DAC960_V4_ReadStatusRegister(ControllerBaseAddress);
|
305 |
|
|
DAC960_V4_AcknowledgeInterrupt(ControllerBaseAddress);
|
306 |
|
|
DAC960_V4_AcknowledgeStatus(ControllerBaseAddress);
|
307 |
|
|
return CommandStatus == DAC960_NormalCompletion;
|
308 |
|
|
}
|
309 |
|
|
|
310 |
|
|
|
311 |
|
|
/*
|
312 |
|
|
DAC960_DetectControllers detects DAC960 PCI RAID Controllers by interrogating
|
313 |
|
|
the PCI Configuration Space for DeviceID.
|
314 |
|
|
*/
|
315 |
|
|
|
316 |
|
|
static void DAC960_DetectControllers(unsigned short DeviceID)
|
317 |
|
|
{
|
318 |
|
|
unsigned char Bus, DeviceFunction, IRQ_Channel;
|
319 |
|
|
unsigned int BaseAddress0, BaseAddress1;
|
320 |
|
|
unsigned int MemoryWindowSize = 0;
|
321 |
|
|
unsigned short Index = 0;
|
322 |
|
|
while (pcibios_find_device(PCI_VENDOR_ID_MYLEX, DeviceID,
|
323 |
|
|
Index++, &Bus, &DeviceFunction) == 0)
|
324 |
|
|
{
|
325 |
|
|
DAC960_Controller_T *Controller = (DAC960_Controller_T *)
|
326 |
|
|
kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC);
|
327 |
|
|
DAC960_ControllerType_T ControllerType = 0;
|
328 |
|
|
DAC960_IO_Address_T IO_Address = 0;
|
329 |
|
|
DAC960_PCI_Address_T PCI_Address = 0;
|
330 |
|
|
unsigned char Device = DeviceFunction >> 3;
|
331 |
|
|
unsigned char Function = DeviceFunction & 0x7;
|
332 |
|
|
pcibios_read_config_dword(Bus, DeviceFunction,
|
333 |
|
|
PCI_BASE_ADDRESS_0, &BaseAddress0);
|
334 |
|
|
pcibios_read_config_dword(Bus, DeviceFunction,
|
335 |
|
|
PCI_BASE_ADDRESS_1, &BaseAddress1);
|
336 |
|
|
pcibios_read_config_byte(Bus, DeviceFunction,
|
337 |
|
|
PCI_INTERRUPT_LINE, &IRQ_Channel);
|
338 |
|
|
switch (DeviceID)
|
339 |
|
|
{
|
340 |
|
|
case PCI_DEVICE_ID_MYLEX_DAC960P_V4:
|
341 |
|
|
ControllerType = DAC960_V4_Controller;
|
342 |
|
|
PCI_Address = BaseAddress0 & PCI_BASE_ADDRESS_MEM_MASK;
|
343 |
|
|
MemoryWindowSize = DAC960_V4_RegisterWindowSize;
|
344 |
|
|
break;
|
345 |
|
|
case PCI_DEVICE_ID_MYLEX_DAC960P_V3:
|
346 |
|
|
ControllerType = DAC960_V3_Controller;
|
347 |
|
|
IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
|
348 |
|
|
PCI_Address = BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK;
|
349 |
|
|
MemoryWindowSize = DAC960_V3_RegisterWindowSize;
|
350 |
|
|
break;
|
351 |
|
|
}
|
352 |
|
|
if (DAC960_ControllerCount == DAC960_MaxControllers)
|
353 |
|
|
{
|
354 |
|
|
DAC960_Error("More than %d DAC960 Controllers detected - "
|
355 |
|
|
"ignoring from Controller at\n",
|
356 |
|
|
NULL, DAC960_MaxControllers);
|
357 |
|
|
goto Failure;
|
358 |
|
|
}
|
359 |
|
|
if (Controller == NULL)
|
360 |
|
|
{
|
361 |
|
|
DAC960_Error("Unable to allocate Controller structure for "
|
362 |
|
|
"Controller at\n", NULL);
|
363 |
|
|
goto Failure;
|
364 |
|
|
}
|
365 |
|
|
memset(Controller, 0, sizeof(DAC960_Controller_T));
|
366 |
|
|
Controller->ControllerNumber = DAC960_ControllerCount;
|
367 |
|
|
DAC960_Controllers[DAC960_ControllerCount++] = Controller;
|
368 |
|
|
if (IRQ_Channel == 0 || IRQ_Channel >= NR_IRQS)
|
369 |
|
|
{
|
370 |
|
|
DAC960_Error("IRQ Channel %d illegal for Controller at\n",
|
371 |
|
|
NULL, IRQ_Channel);
|
372 |
|
|
goto Failure;
|
373 |
|
|
}
|
374 |
|
|
Controller->ControllerType = ControllerType;
|
375 |
|
|
Controller->IO_Address = IO_Address;
|
376 |
|
|
Controller->PCI_Address = PCI_Address;
|
377 |
|
|
Controller->Bus = Bus;
|
378 |
|
|
Controller->Device = Device;
|
379 |
|
|
Controller->Function = Function;
|
380 |
|
|
/*
|
381 |
|
|
Acquire shared access to the IRQ Channel.
|
382 |
|
|
*/
|
383 |
|
|
strcpy(Controller->FullModelName, "DAC960");
|
384 |
|
|
if (request_irq(IRQ_Channel, DAC960_InterruptHandler,
|
385 |
|
|
SA_INTERRUPT | SA_SHIRQ, Controller->FullModelName,
|
386 |
|
|
Controller) < 0)
|
387 |
|
|
{
|
388 |
|
|
DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
|
389 |
|
|
NULL, IRQ_Channel);
|
390 |
|
|
goto Failure;
|
391 |
|
|
}
|
392 |
|
|
Controller->IRQ_Channel = IRQ_Channel;
|
393 |
|
|
/*
|
394 |
|
|
Map the Controller Register Window.
|
395 |
|
|
*/
|
396 |
|
|
if (MemoryWindowSize < PAGE_SIZE)
|
397 |
|
|
MemoryWindowSize = PAGE_SIZE;
|
398 |
|
|
Controller->MemoryMappedAddress =
|
399 |
|
|
ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize);
|
400 |
|
|
Controller->BaseAddress =
|
401 |
|
|
Controller->MemoryMappedAddress + (PCI_Address & ~PAGE_MASK);
|
402 |
|
|
if (Controller->MemoryMappedAddress == NULL)
|
403 |
|
|
{
|
404 |
|
|
DAC960_Error("Unable to map Controller Register Window for "
|
405 |
|
|
"Controller at\n", NULL);
|
406 |
|
|
goto Failure;
|
407 |
|
|
}
|
408 |
|
|
switch (DeviceID)
|
409 |
|
|
{
|
410 |
|
|
case PCI_DEVICE_ID_MYLEX_DAC960P_V4:
|
411 |
|
|
DAC960_V4_DisableInterrupts(Controller->BaseAddress);
|
412 |
|
|
if (!DAC960_V4_EnableMemoryMailboxInterface(Controller))
|
413 |
|
|
{
|
414 |
|
|
DAC960_Error("Unable to Enable V4 Memory Mailbox Interface "
|
415 |
|
|
"for Controller at\n", NULL);
|
416 |
|
|
goto Failure;
|
417 |
|
|
}
|
418 |
|
|
DAC960_V4_EnableInterrupts(Controller->BaseAddress);
|
419 |
|
|
break;
|
420 |
|
|
case PCI_DEVICE_ID_MYLEX_DAC960P_V3:
|
421 |
|
|
request_region(Controller->IO_Address, 0x80,
|
422 |
|
|
Controller->FullModelName);
|
423 |
|
|
DAC960_V3_EnableInterrupts(Controller->BaseAddress);
|
424 |
|
|
break;
|
425 |
|
|
}
|
426 |
|
|
Controller->Commands[0].Controller = Controller;
|
427 |
|
|
Controller->Commands[0].Next = NULL;
|
428 |
|
|
Controller->FreeCommands = &Controller->Commands[0];
|
429 |
|
|
continue;
|
430 |
|
|
Failure:
|
431 |
|
|
if (IO_Address == 0)
|
432 |
|
|
DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A "
|
433 |
|
|
"PCI Address 0x%X\n", NULL,
|
434 |
|
|
Bus, Device, Function, PCI_Address);
|
435 |
|
|
else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "
|
436 |
|
|
"0x%X PCI Address 0x%X\n", NULL,
|
437 |
|
|
Bus, Device, Function, IO_Address, PCI_Address);
|
438 |
|
|
if (Controller == NULL) break;
|
439 |
|
|
if (Controller->IRQ_Channel > 0)
|
440 |
|
|
free_irq(IRQ_Channel, Controller);
|
441 |
|
|
if (Controller->MemoryMappedAddress != NULL)
|
442 |
|
|
iounmap(Controller->MemoryMappedAddress);
|
443 |
|
|
kfree(Controller);
|
444 |
|
|
break;
|
445 |
|
|
}
|
446 |
|
|
}
|
447 |
|
|
|
448 |
|
|
|
449 |
|
|
/*
|
450 |
|
|
DAC960_ReadControllerConfiguration reads the Configuration Information
|
451 |
|
|
from Controller and initializes the Controller structure.
|
452 |
|
|
*/
|
453 |
|
|
|
454 |
|
|
static boolean DAC960_ReadControllerConfiguration(DAC960_Controller_T
|
455 |
|
|
*Controller)
|
456 |
|
|
{
|
457 |
|
|
DAC960_Enquiry2_T Enquiry2;
|
458 |
|
|
DAC960_Config2_T Config2;
|
459 |
|
|
int Channel, TargetID;
|
460 |
|
|
if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry,
|
461 |
|
|
&Controller->Enquiry[0]))
|
462 |
|
|
return DAC960_Failure(Controller, "ENQUIRY");
|
463 |
|
|
if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry2, &Enquiry2))
|
464 |
|
|
return DAC960_Failure(Controller, "ENQUIRY2");
|
465 |
|
|
if (!DAC960_ExecuteType3(Controller, DAC960_ReadConfig2, &Config2))
|
466 |
|
|
return DAC960_Failure(Controller, "READ CONFIG2");
|
467 |
|
|
if (!DAC960_ExecuteType3(Controller, DAC960_GetLogicalDriveInformation,
|
468 |
|
|
&Controller->LogicalDriveInformation[0]))
|
469 |
|
|
return DAC960_Failure(Controller, "GET LOGICAL DRIVE INFORMATION");
|
470 |
|
|
for (Channel = 0; Channel < Enquiry2.ActualChannels; Channel++)
|
471 |
|
|
for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
|
472 |
|
|
if (!DAC960_ExecuteType3D(Controller, DAC960_GetDeviceState,
|
473 |
|
|
Channel, TargetID,
|
474 |
|
|
&Controller->DeviceState[0][Channel][TargetID]))
|
475 |
|
|
return DAC960_Failure(Controller, "GET DEVICE STATE");
|
476 |
|
|
/*
|
477 |
|
|
Initialize the Controller Model Name and Full Model Name fields.
|
478 |
|
|
*/
|
479 |
|
|
switch (Enquiry2.HardwareID.SubModel)
|
480 |
|
|
{
|
481 |
|
|
case DAC960_P_PD_PU:
|
482 |
|
|
if (Enquiry2.SCSICapability.BusSpeed == DAC960_Ultra)
|
483 |
|
|
strcpy(Controller->ModelName, "DAC960PU");
|
484 |
|
|
else strcpy(Controller->ModelName, "DAC960PD");
|
485 |
|
|
break;
|
486 |
|
|
case DAC960_PL:
|
487 |
|
|
strcpy(Controller->ModelName, "DAC960PL");
|
488 |
|
|
break;
|
489 |
|
|
case DAC960_PG:
|
490 |
|
|
strcpy(Controller->ModelName, "DAC960PG");
|
491 |
|
|
break;
|
492 |
|
|
case DAC960_PJ:
|
493 |
|
|
strcpy(Controller->ModelName, "DAC960PJ");
|
494 |
|
|
break;
|
495 |
|
|
case DAC960_PTL_0:
|
496 |
|
|
strcpy(Controller->ModelName, "DAC960PTL-0");
|
497 |
|
|
break;
|
498 |
|
|
case DAC960_PTL_1:
|
499 |
|
|
strcpy(Controller->ModelName, "DAC960PTL-1");
|
500 |
|
|
break;
|
501 |
|
|
default:
|
502 |
|
|
return DAC960_Failure(Controller, "MODEL VERIFICATION");
|
503 |
|
|
}
|
504 |
|
|
strcpy(Controller->FullModelName, "Mylex ");
|
505 |
|
|
strcat(Controller->FullModelName, Controller->ModelName);
|
506 |
|
|
/*
|
507 |
|
|
Initialize the Controller Firmware Version field and verify that it
|
508 |
|
|
is a supported firmware version. The supported firmware versions are:
|
509 |
|
|
|
510 |
|
|
DAC960PTL/PJ/PG 4.06 and above
|
511 |
|
|
DAC960PU/PD/PL 3.51 and above
|
512 |
|
|
*/
|
513 |
|
|
sprintf(Controller->FirmwareVersion, "%d.%02d-%c-%02d",
|
514 |
|
|
Enquiry2.FirmwareID.MajorVersion, Enquiry2.FirmwareID.MinorVersion,
|
515 |
|
|
Enquiry2.FirmwareID.FirmwareType, Enquiry2.FirmwareID.TurnID);
|
516 |
|
|
if (!((Controller->FirmwareVersion[0] == '4' &&
|
517 |
|
|
strcmp(Controller->FirmwareVersion, "4.06") >= 0) ||
|
518 |
|
|
(Controller->FirmwareVersion[0] == '3' &&
|
519 |
|
|
strcmp(Controller->FirmwareVersion, "3.51") >= 0)))
|
520 |
|
|
{
|
521 |
|
|
DAC960_Failure(Controller, "FIRMWARE VERSION VERIFICATION");
|
522 |
|
|
DAC960_Error("Firmware Version = '%s'\n", Controller,
|
523 |
|
|
Controller->FirmwareVersion);
|
524 |
|
|
return false;
|
525 |
|
|
}
|
526 |
|
|
/*
|
527 |
|
|
Initialize the Controller Channels, Memory Size, and SAF-TE Fault
|
528 |
|
|
Management Enabled fields.
|
529 |
|
|
*/
|
530 |
|
|
Controller->Channels = Enquiry2.ActualChannels;
|
531 |
|
|
Controller->MemorySize = Enquiry2.MemorySize >> 20;
|
532 |
|
|
Controller->SAFTE_FaultManagementEnabled =
|
533 |
|
|
Enquiry2.FaultManagementType == DAC960_SAFTE;
|
534 |
|
|
/*
|
535 |
|
|
Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive
|
536 |
|
|
Count, Maximum Blocks per Command, and Maximum Scatter/Gather Segments.
|
537 |
|
|
The Driver Queue Depth must be at most one less than the Controller Queue
|
538 |
|
|
Depth to allow for an automatic drive rebuild operation.
|
539 |
|
|
*/
|
540 |
|
|
Controller->ControllerQueueDepth = Controller->Enquiry[0].MaxCommands;
|
541 |
|
|
Controller->DriverQueueDepth = Controller->ControllerQueueDepth - 1;
|
542 |
|
|
Controller->LogicalDriveCount = Controller->Enquiry[0].NumberOfLogicalDrives;
|
543 |
|
|
Controller->MaxBlocksPerCommand = Enquiry2.MaxBlocksPerCommand;
|
544 |
|
|
Controller->MaxScatterGatherSegments = Enquiry2.MaxScatterGatherEntries;
|
545 |
|
|
/*
|
546 |
|
|
Initialize the Stripe Size, Segment Size, and Geometry Translation.
|
547 |
|
|
*/
|
548 |
|
|
Controller->StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor
|
549 |
|
|
>> (10 - DAC960_BlockSizeBits);
|
550 |
|
|
Controller->SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor
|
551 |
|
|
>> (10 - DAC960_BlockSizeBits);
|
552 |
|
|
switch (Config2.DriveGeometry)
|
553 |
|
|
{
|
554 |
|
|
case DAC960_Geometry_128_32:
|
555 |
|
|
Controller->GeometryTranslationHeads = 128;
|
556 |
|
|
Controller->GeometryTranslationSectors = 32;
|
557 |
|
|
break;
|
558 |
|
|
case DAC960_Geometry_255_63:
|
559 |
|
|
Controller->GeometryTranslationHeads = 255;
|
560 |
|
|
Controller->GeometryTranslationSectors = 63;
|
561 |
|
|
break;
|
562 |
|
|
default:
|
563 |
|
|
return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY");
|
564 |
|
|
}
|
565 |
|
|
return true;
|
566 |
|
|
}
|
567 |
|
|
|
568 |
|
|
|
569 |
|
|
/*
|
570 |
|
|
DAC960_ReportControllerConfiguration reports the configuration of
|
571 |
|
|
Controller.
|
572 |
|
|
*/
|
573 |
|
|
|
574 |
|
|
static boolean DAC960_ReportControllerConfiguration(DAC960_Controller_T
|
575 |
|
|
*Controller)
|
576 |
|
|
{
|
577 |
|
|
int LogicalDriveNumber, Channel, TargetID;
|
578 |
|
|
DAC960_Info("Configuring Mylex %s PCI RAID Controller\n",
|
579 |
|
|
Controller, Controller->ModelName);
|
580 |
|
|
DAC960_Info(" Firmware Version: %s, Channels: %d, Memory Size: %dMB\n",
|
581 |
|
|
Controller, Controller->FirmwareVersion,
|
582 |
|
|
Controller->Channels, Controller->MemorySize);
|
583 |
|
|
DAC960_Info(" PCI Bus: %d, Device: %d, Function: %d, I/O Address: ",
|
584 |
|
|
Controller, Controller->Bus,
|
585 |
|
|
Controller->Device, Controller->Function);
|
586 |
|
|
if (Controller->IO_Address == 0)
|
587 |
|
|
DAC960_Info("Unassigned\n", Controller);
|
588 |
|
|
else DAC960_Info("0x%X\n", Controller, Controller->IO_Address);
|
589 |
|
|
DAC960_Info(" PCI Address: 0x%X mapped at 0x%lX, IRQ Channel: %d\n",
|
590 |
|
|
Controller, Controller->PCI_Address,
|
591 |
|
|
(unsigned long) Controller->BaseAddress,
|
592 |
|
|
Controller->IRQ_Channel);
|
593 |
|
|
DAC960_Info(" Controller Queue Depth: %d, "
|
594 |
|
|
"Maximum Blocks per Command: %d\n",
|
595 |
|
|
Controller, Controller->ControllerQueueDepth,
|
596 |
|
|
Controller->MaxBlocksPerCommand);
|
597 |
|
|
DAC960_Info(" Driver Queue Depth: %d, "
|
598 |
|
|
"Maximum Scatter/Gather Segments: %d\n",
|
599 |
|
|
Controller, Controller->DriverQueueDepth,
|
600 |
|
|
Controller->MaxScatterGatherSegments);
|
601 |
|
|
DAC960_Info(" Stripe Size: %dKB, Segment Size: %dKB, "
|
602 |
|
|
"BIOS Geometry: %d/%d\n", Controller,
|
603 |
|
|
Controller->StripeSize,
|
604 |
|
|
Controller->SegmentSize,
|
605 |
|
|
Controller->GeometryTranslationHeads,
|
606 |
|
|
Controller->GeometryTranslationSectors);
|
607 |
|
|
if (Controller->SAFTE_FaultManagementEnabled)
|
608 |
|
|
DAC960_Info(" SAF-TE Fault Management Enabled\n", Controller);
|
609 |
|
|
DAC960_Info(" Physical Devices:\n", Controller);
|
610 |
|
|
for (Channel = 0; Channel < Controller->Channels; Channel++)
|
611 |
|
|
for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
|
612 |
|
|
{
|
613 |
|
|
DAC960_DeviceState_T *DeviceState =
|
614 |
|
|
&Controller->DeviceState[0][Channel][TargetID];
|
615 |
|
|
if (!DeviceState->Present) continue;
|
616 |
|
|
switch (DeviceState->DeviceType)
|
617 |
|
|
{
|
618 |
|
|
case DAC960_OtherType:
|
619 |
|
|
DAC960_Info(" %d:%d - Other\n", Controller, Channel, TargetID);
|
620 |
|
|
break;
|
621 |
|
|
case DAC960_DiskType:
|
622 |
|
|
DAC960_Info(" %d:%d - Disk: %s, %d blocks\n", Controller,
|
623 |
|
|
Channel, TargetID,
|
624 |
|
|
(DeviceState->DeviceState == DAC960_Device_Dead
|
625 |
|
|
? "Dead"
|
626 |
|
|
: DeviceState->DeviceState == DAC960_Device_WriteOnly
|
627 |
|
|
? "Write-Only"
|
628 |
|
|
: DeviceState->DeviceState == DAC960_Device_Online
|
629 |
|
|
? "Online" : "Standby"),
|
630 |
|
|
DeviceState->DiskSize);
|
631 |
|
|
break;
|
632 |
|
|
case DAC960_SequentialType:
|
633 |
|
|
DAC960_Info(" %d:%d - Sequential\n", Controller,
|
634 |
|
|
Channel, TargetID);
|
635 |
|
|
break;
|
636 |
|
|
case DAC960_CDROM_or_WORM_Type:
|
637 |
|
|
DAC960_Info(" %d:%d - CD-ROM or WORM\n", Controller,
|
638 |
|
|
Channel, TargetID);
|
639 |
|
|
break;
|
640 |
|
|
}
|
641 |
|
|
|
642 |
|
|
}
|
643 |
|
|
DAC960_Info(" Logical Drives:\n", Controller);
|
644 |
|
|
for (LogicalDriveNumber = 0;
|
645 |
|
|
LogicalDriveNumber < Controller->LogicalDriveCount;
|
646 |
|
|
LogicalDriveNumber++)
|
647 |
|
|
{
|
648 |
|
|
DAC960_LogicalDriveInformation_T *LogicalDriveInformation =
|
649 |
|
|
&Controller->LogicalDriveInformation[0][LogicalDriveNumber];
|
650 |
|
|
DAC960_Info(" /dev/rd/c%dd%d: RAID-%d, %s, %d blocks, %s\n",
|
651 |
|
|
Controller, Controller->ControllerNumber, LogicalDriveNumber,
|
652 |
|
|
LogicalDriveInformation->RAIDLevel,
|
653 |
|
|
(LogicalDriveInformation->LogicalDriveState ==
|
654 |
|
|
DAC960_LogicalDrive_Online
|
655 |
|
|
? "Online"
|
656 |
|
|
: LogicalDriveInformation->LogicalDriveState ==
|
657 |
|
|
DAC960_LogicalDrive_Critical
|
658 |
|
|
? "Critical" : "Offline"),
|
659 |
|
|
LogicalDriveInformation->LogicalDriveSize,
|
660 |
|
|
(LogicalDriveInformation->WriteBack
|
661 |
|
|
? "Write Back" : "Write Thru"));
|
662 |
|
|
}
|
663 |
|
|
DAC960_Info("\n", Controller);
|
664 |
|
|
return true;
|
665 |
|
|
}
|
666 |
|
|
|
667 |
|
|
|
668 |
|
|
/*
|
669 |
|
|
DAC960_RegisterBlockDevice registers the Block Device structures
|
670 |
|
|
associated with Controller.
|
671 |
|
|
*/
|
672 |
|
|
|
673 |
|
|
static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
|
674 |
|
|
{
|
675 |
|
|
static void (*RequestFunctions[DAC960_MaxControllers])(void) =
|
676 |
|
|
{ DAC960_RequestFunction0, DAC960_RequestFunction1,
|
677 |
|
|
DAC960_RequestFunction2, DAC960_RequestFunction3,
|
678 |
|
|
DAC960_RequestFunction4, DAC960_RequestFunction5,
|
679 |
|
|
DAC960_RequestFunction6, DAC960_RequestFunction7 };
|
680 |
|
|
int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
|
681 |
|
|
GenericDiskInfo_T *GenericDiskInfo;
|
682 |
|
|
int MinorNumber;
|
683 |
|
|
/*
|
684 |
|
|
Register the Block Device Major Number for this DAC960 Controller.
|
685 |
|
|
*/
|
686 |
|
|
if (register_blkdev(MajorNumber, "rd", &DAC960_FileOperations) < 0)
|
687 |
|
|
{
|
688 |
|
|
DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n",
|
689 |
|
|
Controller, MajorNumber);
|
690 |
|
|
return false;
|
691 |
|
|
}
|
692 |
|
|
/*
|
693 |
|
|
Initialize the I/O Request Function.
|
694 |
|
|
*/
|
695 |
|
|
blk_dev[MajorNumber].request_fn =
|
696 |
|
|
RequestFunctions[Controller->ControllerNumber];
|
697 |
|
|
/*
|
698 |
|
|
Initialize the Disk Partitions array, Partition Sizes array, Block Sizes
|
699 |
|
|
array, Max Sectors per Request array, and Max Segments per Request array.
|
700 |
|
|
*/
|
701 |
|
|
for (MinorNumber = 0; MinorNumber < DAC960_MinorCount; MinorNumber++)
|
702 |
|
|
{
|
703 |
|
|
Controller->BlockSizes[MinorNumber] = BLOCK_SIZE;
|
704 |
|
|
Controller->MaxSectorsPerRequest[MinorNumber] =
|
705 |
|
|
Controller->MaxBlocksPerCommand;
|
706 |
|
|
Controller->MaxSegmentsPerRequest[MinorNumber] =
|
707 |
|
|
Controller->MaxScatterGatherSegments;
|
708 |
|
|
}
|
709 |
|
|
Controller->GenericDiskInfo.part = Controller->DiskPartitions;
|
710 |
|
|
Controller->GenericDiskInfo.sizes = Controller->PartitionSizes;
|
711 |
|
|
blksize_size[MajorNumber] = Controller->BlockSizes;
|
712 |
|
|
max_sectors[MajorNumber] = Controller->MaxSectorsPerRequest;
|
713 |
|
|
max_segments[MajorNumber] = Controller->MaxSegmentsPerRequest;
|
714 |
|
|
/*
|
715 |
|
|
Initialize Read Ahead to 128 sectors.
|
716 |
|
|
*/
|
717 |
|
|
read_ahead[MajorNumber] = 128;
|
718 |
|
|
/*
|
719 |
|
|
Complete initialization of the Generic Disk Information structure.
|
720 |
|
|
*/
|
721 |
|
|
Controller->GenericDiskInfo.major = MajorNumber;
|
722 |
|
|
Controller->GenericDiskInfo.major_name = "rd";
|
723 |
|
|
Controller->GenericDiskInfo.minor_shift = DAC960_MaxPartitionsBits;
|
724 |
|
|
Controller->GenericDiskInfo.max_p = DAC960_MaxPartitions;
|
725 |
|
|
Controller->GenericDiskInfo.max_nr = DAC960_MaxLogicalDrives;
|
726 |
|
|
Controller->GenericDiskInfo.init = DAC960_InitializeGenericDiskInfo;
|
727 |
|
|
Controller->GenericDiskInfo.nr_real = Controller->LogicalDriveCount;
|
728 |
|
|
Controller->GenericDiskInfo.real_devices = Controller;
|
729 |
|
|
Controller->GenericDiskInfo.next = NULL;
|
730 |
|
|
/*
|
731 |
|
|
Install the Generic Disk Information structure at the end of the list.
|
732 |
|
|
*/
|
733 |
|
|
if ((GenericDiskInfo = gendisk_head) != NULL)
|
734 |
|
|
{
|
735 |
|
|
while (GenericDiskInfo->next != NULL)
|
736 |
|
|
GenericDiskInfo = GenericDiskInfo->next;
|
737 |
|
|
GenericDiskInfo->next = &Controller->GenericDiskInfo;
|
738 |
|
|
}
|
739 |
|
|
else gendisk_head = &Controller->GenericDiskInfo;
|
740 |
|
|
/*
|
741 |
|
|
Indicate the Block Device Registration completed successfully,
|
742 |
|
|
*/
|
743 |
|
|
return true;
|
744 |
|
|
}
|
745 |
|
|
|
746 |
|
|
|
747 |
|
|
/*
|
748 |
|
|
DAC960_UnregisterBlockDevice unregisters the Block Device structures
|
749 |
|
|
associated with Controller.
|
750 |
|
|
*/
|
751 |
|
|
|
752 |
|
|
static void DAC960_UnregisterBlockDevice(DAC960_Controller_T *Controller)
|
753 |
|
|
{
|
754 |
|
|
int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
|
755 |
|
|
/*
|
756 |
|
|
Unregister the Block Device Major Number for this DAC960 Controller.
|
757 |
|
|
*/
|
758 |
|
|
unregister_blkdev(MajorNumber, "rd");
|
759 |
|
|
/*
|
760 |
|
|
Remove the I/O Request Function.
|
761 |
|
|
*/
|
762 |
|
|
blk_dev[MajorNumber].request_fn = NULL;
|
763 |
|
|
/*
|
764 |
|
|
Remove the Disk Partitions array, Partition Sizes array, Block Sizes
|
765 |
|
|
array, Max Sectors per Request array, and Max Segments per Request array.
|
766 |
|
|
*/
|
767 |
|
|
Controller->GenericDiskInfo.part = NULL;
|
768 |
|
|
Controller->GenericDiskInfo.sizes = NULL;
|
769 |
|
|
blk_size[MajorNumber] = NULL;
|
770 |
|
|
blksize_size[MajorNumber] = NULL;
|
771 |
|
|
max_sectors[MajorNumber] = NULL;
|
772 |
|
|
max_segments[MajorNumber] = NULL;
|
773 |
|
|
/*
|
774 |
|
|
Remove the Generic Disk Information structure from the list.
|
775 |
|
|
*/
|
776 |
|
|
if (gendisk_head != &Controller->GenericDiskInfo)
|
777 |
|
|
{
|
778 |
|
|
GenericDiskInfo_T *GenericDiskInfo = gendisk_head;
|
779 |
|
|
while (GenericDiskInfo != NULL &&
|
780 |
|
|
GenericDiskInfo->next != &Controller->GenericDiskInfo)
|
781 |
|
|
GenericDiskInfo = GenericDiskInfo->next;
|
782 |
|
|
if (GenericDiskInfo != NULL)
|
783 |
|
|
GenericDiskInfo->next = GenericDiskInfo->next->next;
|
784 |
|
|
}
|
785 |
|
|
else gendisk_head = Controller->GenericDiskInfo.next;
|
786 |
|
|
}
|
787 |
|
|
|
788 |
|
|
|
789 |
|
|
/*
|
790 |
|
|
DAC960_InitializeController initializes Controller.
|
791 |
|
|
*/
|
792 |
|
|
|
793 |
|
|
static void DAC960_InitializeController(DAC960_Controller_T *Controller)
|
794 |
|
|
{
|
795 |
|
|
DAC960_AnnounceDriver(Controller);
|
796 |
|
|
if (DAC960_ReadControllerConfiguration(Controller) &&
|
797 |
|
|
DAC960_ReportControllerConfiguration(Controller) &&
|
798 |
|
|
DAC960_RegisterBlockDevice(Controller))
|
799 |
|
|
{
|
800 |
|
|
/*
|
801 |
|
|
Initialize the Command structures.
|
802 |
|
|
*/
|
803 |
|
|
DAC960_Command_T *Commands = Controller->Commands;
|
804 |
|
|
int CommandIdentifier;
|
805 |
|
|
Controller->FreeCommands = NULL;
|
806 |
|
|
for (CommandIdentifier = 0;
|
807 |
|
|
CommandIdentifier < Controller->DriverQueueDepth;
|
808 |
|
|
CommandIdentifier++)
|
809 |
|
|
{
|
810 |
|
|
Commands[CommandIdentifier].Controller = Controller;
|
811 |
|
|
Commands[CommandIdentifier].Next = Controller->FreeCommands;
|
812 |
|
|
Controller->FreeCommands = &Commands[CommandIdentifier];
|
813 |
|
|
}
|
814 |
|
|
/*
|
815 |
|
|
Initialize the Monitoring Timer.
|
816 |
|
|
*/
|
817 |
|
|
init_timer(&Controller->MonitoringTimer);
|
818 |
|
|
Controller->MonitoringTimer.expires =
|
819 |
|
|
jiffies + DAC960_MonitoringTimerInterval;
|
820 |
|
|
Controller->MonitoringTimer.data = (unsigned long) Controller;
|
821 |
|
|
Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction;
|
822 |
|
|
add_timer(&Controller->MonitoringTimer);
|
823 |
|
|
}
|
824 |
|
|
else
|
825 |
|
|
{
|
826 |
|
|
free_irq(Controller->IRQ_Channel, Controller);
|
827 |
|
|
iounmap(Controller->MemoryMappedAddress);
|
828 |
|
|
DAC960_UnregisterBlockDevice(Controller);
|
829 |
|
|
DAC960_Controllers[Controller->ControllerNumber] = NULL;
|
830 |
|
|
kfree(Controller);
|
831 |
|
|
}
|
832 |
|
|
}
|
833 |
|
|
|
834 |
|
|
|
835 |
|
|
/*
|
836 |
|
|
DAC960_Initialize initializes the DAC960 Driver.
|
837 |
|
|
*/
|
838 |
|
|
|
839 |
|
|
void DAC960_Initialize(void)
|
840 |
|
|
{
|
841 |
|
|
int ControllerNumber;
|
842 |
|
|
DAC960_DetectControllers(PCI_DEVICE_ID_MYLEX_DAC960P_V4);
|
843 |
|
|
DAC960_DetectControllers(PCI_DEVICE_ID_MYLEX_DAC960P_V3);
|
844 |
|
|
for (ControllerNumber = 0;
|
845 |
|
|
ControllerNumber < DAC960_ControllerCount;
|
846 |
|
|
ControllerNumber++)
|
847 |
|
|
if (DAC960_Controllers[ControllerNumber] != NULL)
|
848 |
|
|
DAC960_InitializeController(DAC960_Controllers[ControllerNumber]);
|
849 |
|
|
}
|
850 |
|
|
|
851 |
|
|
|
852 |
|
|
/*
|
853 |
|
|
DAC960_Finalize flushes all DAC960 caches before the system halts.
|
854 |
|
|
*/
|
855 |
|
|
|
856 |
|
|
void DAC960_Finalize(void)
|
857 |
|
|
{
|
858 |
|
|
int ControllerNumber;
|
859 |
|
|
for (ControllerNumber = 0;
|
860 |
|
|
ControllerNumber < DAC960_ControllerCount;
|
861 |
|
|
ControllerNumber++)
|
862 |
|
|
{
|
863 |
|
|
DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
|
864 |
|
|
if (Controller == NULL) continue;
|
865 |
|
|
DAC960_Notice("Flushing Cache...", Controller);
|
866 |
|
|
DAC960_ExecuteType3(Controller, DAC960_Flush, NULL);
|
867 |
|
|
DAC960_Notice("done\n", Controller);
|
868 |
|
|
}
|
869 |
|
|
}
|
870 |
|
|
|
871 |
|
|
|
872 |
|
|
/*
|
873 |
|
|
DAC960_ProcessRequest attempts to remove one I/O Request from Controller's
|
874 |
|
|
I/O Request Queue and queues it to the Controller. Command is either a
|
875 |
|
|
previously allocated Command to be reused, or NULL if a new Command is to
|
876 |
|
|
be allocated for this I/O Request. It returns true if an I/O Request was
|
877 |
|
|
queued and false otherwise.
|
878 |
|
|
*/
|
879 |
|
|
|
880 |
|
|
static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller,
|
881 |
|
|
DAC960_Command_T *Command)
|
882 |
|
|
{
|
883 |
|
|
int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
|
884 |
|
|
IO_Request_T *Request = blk_dev[MajorNumber].current_request;
|
885 |
|
|
DAC960_CommandMailbox_T *CommandMailbox;
|
886 |
|
|
char *RequestBuffer;
|
887 |
|
|
if (Request == NULL || Request->rq_status == RQ_INACTIVE) return false;
|
888 |
|
|
if (Command == NULL)
|
889 |
|
|
Command = DAC960_AllocateCommand(Controller);
|
890 |
|
|
if (Command == NULL) return false;
|
891 |
|
|
DAC960_ClearCommand(Command);
|
892 |
|
|
if (Request->cmd == READ)
|
893 |
|
|
Command->CommandType = DAC960_ReadCommand;
|
894 |
|
|
else Command->CommandType = DAC960_WriteCommand;
|
895 |
|
|
Command->Semaphore = Request->sem;
|
896 |
|
|
Command->LogicalDriveNumber = DAC960_LogicalDriveNumber(Request->rq_dev);
|
897 |
|
|
Command->BlockNumber =
|
898 |
|
|
Request->sector
|
899 |
|
|
+ Controller->GenericDiskInfo.part[MINOR(Request->rq_dev)].start_sect;
|
900 |
|
|
Command->BlockCount = Request->nr_sectors;
|
901 |
|
|
Command->SegmentCount = Request->nr_segments;
|
902 |
|
|
Command->BufferHeader = Request->bh;
|
903 |
|
|
RequestBuffer = Request->buffer;
|
904 |
|
|
Request->rq_status = RQ_INACTIVE;
|
905 |
|
|
blk_dev[MajorNumber].current_request = Request->next;
|
906 |
|
|
wake_up(&wait_for_request);
|
907 |
|
|
CommandMailbox = &Command->CommandMailbox;
|
908 |
|
|
if (Command->SegmentCount == 1)
|
909 |
|
|
{
|
910 |
|
|
if (Command->CommandType == DAC960_ReadCommand)
|
911 |
|
|
CommandMailbox->Type5.CommandOpcode = DAC960_Read;
|
912 |
|
|
else CommandMailbox->Type5.CommandOpcode = DAC960_Write;
|
913 |
|
|
CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
|
914 |
|
|
CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
|
915 |
|
|
CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
|
916 |
|
|
CommandMailbox->Type5.BusAddress = Virtual_to_Bus(RequestBuffer);
|
917 |
|
|
}
|
918 |
|
|
else
|
919 |
|
|
{
|
920 |
|
|
DAC960_ScatterGatherSegment_T
|
921 |
|
|
*ScatterGatherList = Command->ScatterGatherList;
|
922 |
|
|
BufferHeader_T *BufferHeader = Command->BufferHeader;
|
923 |
|
|
char *LastDataEndPointer = NULL;
|
924 |
|
|
int SegmentNumber = 0;
|
925 |
|
|
if (Command->CommandType == DAC960_ReadCommand)
|
926 |
|
|
CommandMailbox->Type5.CommandOpcode = DAC960_ReadWithOldScatterGather;
|
927 |
|
|
else
|
928 |
|
|
CommandMailbox->Type5.CommandOpcode = DAC960_WriteWithOldScatterGather;
|
929 |
|
|
CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
|
930 |
|
|
CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
|
931 |
|
|
CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
|
932 |
|
|
CommandMailbox->Type5.BusAddress = Virtual_to_Bus(ScatterGatherList);
|
933 |
|
|
CommandMailbox->Type5.ScatterGatherCount = Command->SegmentCount;
|
934 |
|
|
while (BufferHeader != NULL)
|
935 |
|
|
{
|
936 |
|
|
if (BufferHeader->b_data == LastDataEndPointer)
|
937 |
|
|
{
|
938 |
|
|
ScatterGatherList[SegmentNumber-1].SegmentByteCount +=
|
939 |
|
|
BufferHeader->b_size;
|
940 |
|
|
LastDataEndPointer += BufferHeader->b_size;
|
941 |
|
|
}
|
942 |
|
|
else
|
943 |
|
|
{
|
944 |
|
|
ScatterGatherList[SegmentNumber].SegmentDataPointer =
|
945 |
|
|
Virtual_to_Bus(BufferHeader->b_data);
|
946 |
|
|
ScatterGatherList[SegmentNumber].SegmentByteCount =
|
947 |
|
|
BufferHeader->b_size;
|
948 |
|
|
LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size;
|
949 |
|
|
if (SegmentNumber++ > Controller->MaxScatterGatherSegments)
|
950 |
|
|
panic("DAC960: Scatter/Gather Segment Overflow\n");
|
951 |
|
|
}
|
952 |
|
|
BufferHeader = BufferHeader->b_reqnext;
|
953 |
|
|
}
|
954 |
|
|
if (SegmentNumber != Command->SegmentCount)
|
955 |
|
|
panic("DAC960: SegmentNumber != SegmentCount\n");
|
956 |
|
|
}
|
957 |
|
|
DAC960_QueueCommand(Command);
|
958 |
|
|
return true;
|
959 |
|
|
}
|
960 |
|
|
|
961 |
|
|
|
962 |
|
|
/*
|
963 |
|
|
DAC960_ProcessRequests attempts to remove as many I/O Requests as possible
|
964 |
|
|
from Controller's I/O Request Queue and queue them to the Controller.
|
965 |
|
|
*/
|
966 |
|
|
|
967 |
|
|
static inline void DAC960_ProcessRequests(DAC960_Controller_T *Controller)
|
968 |
|
|
{
|
969 |
|
|
while (Controller->FreeCommands != NULL)
|
970 |
|
|
if (!DAC960_ProcessRequest(Controller, NULL)) break;
|
971 |
|
|
}
|
972 |
|
|
|
973 |
|
|
|
974 |
|
|
/*
|
975 |
|
|
DAC960_RequestFunction0 is the I/O Request Function for DAC960 Controller 0.
|
976 |
|
|
*/
|
977 |
|
|
|
978 |
|
|
static void DAC960_RequestFunction0(void)
|
979 |
|
|
{
|
980 |
|
|
DAC960_Controller_T *Controller = DAC960_Controllers[0];
|
981 |
|
|
ProcessorFlags_T ProcessorFlags;
|
982 |
|
|
/*
|
983 |
|
|
Acquire exclusive access to Controller.
|
984 |
|
|
*/
|
985 |
|
|
DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
|
986 |
|
|
/*
|
987 |
|
|
Process I/O Requests for Controller.
|
988 |
|
|
*/
|
989 |
|
|
DAC960_ProcessRequests(Controller);
|
990 |
|
|
/*
|
991 |
|
|
Release exclusive access to Controller.
|
992 |
|
|
*/
|
993 |
|
|
DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
|
994 |
|
|
}
|
995 |
|
|
|
996 |
|
|
|
997 |
|
|
/*
|
998 |
|
|
DAC960_RequestFunction1 is the I/O Request Function for DAC960 Controller 1.
|
999 |
|
|
*/
|
1000 |
|
|
|
1001 |
|
|
static void DAC960_RequestFunction1(void)
|
1002 |
|
|
{
|
1003 |
|
|
DAC960_Controller_T *Controller = DAC960_Controllers[1];
|
1004 |
|
|
ProcessorFlags_T ProcessorFlags;
|
1005 |
|
|
/*
|
1006 |
|
|
Acquire exclusive access to Controller.
|
1007 |
|
|
*/
|
1008 |
|
|
DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
|
1009 |
|
|
/*
|
1010 |
|
|
Process I/O Requests for Controller.
|
1011 |
|
|
*/
|
1012 |
|
|
DAC960_ProcessRequests(Controller);
|
1013 |
|
|
/*
|
1014 |
|
|
Release exclusive access to Controller.
|
1015 |
|
|
*/
|
1016 |
|
|
DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
|
1017 |
|
|
}
|
1018 |
|
|
|
1019 |
|
|
|
1020 |
|
|
/*
|
1021 |
|
|
DAC960_RequestFunction2 is the I/O Request Function for DAC960 Controller 2.
|
1022 |
|
|
*/
|
1023 |
|
|
|
1024 |
|
|
static void DAC960_RequestFunction2(void)
|
1025 |
|
|
{
|
1026 |
|
|
DAC960_Controller_T *Controller = DAC960_Controllers[2];
|
1027 |
|
|
ProcessorFlags_T ProcessorFlags;
|
1028 |
|
|
/*
|
1029 |
|
|
Acquire exclusive access to Controller.
|
1030 |
|
|
*/
|
1031 |
|
|
DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
|
1032 |
|
|
/*
|
1033 |
|
|
Process I/O Requests for Controller.
|
1034 |
|
|
*/
|
1035 |
|
|
DAC960_ProcessRequests(Controller);
|
1036 |
|
|
/*
|
1037 |
|
|
Release exclusive access to Controller.
|
1038 |
|
|
*/
|
1039 |
|
|
DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
|
1040 |
|
|
}
|
1041 |
|
|
|
1042 |
|
|
|
1043 |
|
|
/*
|
1044 |
|
|
DAC960_RequestFunction3 is the I/O Request Function for DAC960 Controller 3.
|
1045 |
|
|
*/
|
1046 |
|
|
|
1047 |
|
|
static void DAC960_RequestFunction3(void)
|
1048 |
|
|
{
|
1049 |
|
|
DAC960_Controller_T *Controller = DAC960_Controllers[3];
|
1050 |
|
|
ProcessorFlags_T ProcessorFlags;
|
1051 |
|
|
/*
|
1052 |
|
|
Acquire exclusive access to Controller.
|
1053 |
|
|
*/
|
1054 |
|
|
DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
|
1055 |
|
|
/*
|
1056 |
|
|
Process I/O Requests for Controller.
|
1057 |
|
|
*/
|
1058 |
|
|
DAC960_ProcessRequests(Controller);
|
1059 |
|
|
/*
|
1060 |
|
|
Release exclusive access to Controller.
|
1061 |
|
|
*/
|
1062 |
|
|
DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
|
1063 |
|
|
}
|
1064 |
|
|
|
1065 |
|
|
|
1066 |
|
|
/*
|
1067 |
|
|
DAC960_RequestFunction4 is the I/O Request Function for DAC960 Controller 4.
|
1068 |
|
|
*/
|
1069 |
|
|
|
1070 |
|
|
static void DAC960_RequestFunction4(void)
|
1071 |
|
|
{
|
1072 |
|
|
DAC960_Controller_T *Controller = DAC960_Controllers[4];
|
1073 |
|
|
ProcessorFlags_T ProcessorFlags;
|
1074 |
|
|
/*
|
1075 |
|
|
Acquire exclusive access to Controller.
|
1076 |
|
|
*/
|
1077 |
|
|
DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
|
1078 |
|
|
/*
|
1079 |
|
|
Process I/O Requests for Controller.
|
1080 |
|
|
*/
|
1081 |
|
|
DAC960_ProcessRequests(Controller);
|
1082 |
|
|
/*
|
1083 |
|
|
Release exclusive access to Controller.
|
1084 |
|
|
*/
|
1085 |
|
|
DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
|
1086 |
|
|
}
|
1087 |
|
|
|
1088 |
|
|
|
1089 |
|
|
/*
|
1090 |
|
|
DAC960_RequestFunction5 is the I/O Request Function for DAC960 Controller 5.
|
1091 |
|
|
*/
|
1092 |
|
|
|
1093 |
|
|
static void DAC960_RequestFunction5(void)
|
1094 |
|
|
{
|
1095 |
|
|
DAC960_Controller_T *Controller = DAC960_Controllers[5];
|
1096 |
|
|
ProcessorFlags_T ProcessorFlags;
|
1097 |
|
|
/*
|
1098 |
|
|
Acquire exclusive access to Controller.
|
1099 |
|
|
*/
|
1100 |
|
|
DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
|
1101 |
|
|
/*
|
1102 |
|
|
Process I/O Requests for Controller.
|
1103 |
|
|
*/
|
1104 |
|
|
DAC960_ProcessRequests(Controller);
|
1105 |
|
|
/*
|
1106 |
|
|
Release exclusive access to Controller.
|
1107 |
|
|
*/
|
1108 |
|
|
DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
|
1109 |
|
|
}
|
1110 |
|
|
|
1111 |
|
|
|
1112 |
|
|
/*
|
1113 |
|
|
DAC960_RequestFunction6 is the I/O Request Function for DAC960 Controller 6.
|
1114 |
|
|
*/
|
1115 |
|
|
|
1116 |
|
|
static void DAC960_RequestFunction6(void)
|
1117 |
|
|
{
|
1118 |
|
|
DAC960_Controller_T *Controller = DAC960_Controllers[6];
|
1119 |
|
|
ProcessorFlags_T ProcessorFlags;
|
1120 |
|
|
/*
|
1121 |
|
|
Acquire exclusive access to Controller.
|
1122 |
|
|
*/
|
1123 |
|
|
DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
|
1124 |
|
|
/*
|
1125 |
|
|
Process I/O Requests for Controller.
|
1126 |
|
|
*/
|
1127 |
|
|
DAC960_ProcessRequests(Controller);
|
1128 |
|
|
/*
|
1129 |
|
|
Release exclusive access to Controller.
|
1130 |
|
|
*/
|
1131 |
|
|
DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
|
1132 |
|
|
}
|
1133 |
|
|
|
1134 |
|
|
|
1135 |
|
|
/*
|
1136 |
|
|
DAC960_RequestFunction7 is the I/O Request Function for DAC960 Controller 7.
|
1137 |
|
|
*/
|
1138 |
|
|
|
1139 |
|
|
static void DAC960_RequestFunction7(void)
|
1140 |
|
|
{
|
1141 |
|
|
DAC960_Controller_T *Controller = DAC960_Controllers[7];
|
1142 |
|
|
ProcessorFlags_T ProcessorFlags;
|
1143 |
|
|
/*
|
1144 |
|
|
Acquire exclusive access to Controller.
|
1145 |
|
|
*/
|
1146 |
|
|
DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
|
1147 |
|
|
/*
|
1148 |
|
|
Process I/O Requests for Controller.
|
1149 |
|
|
*/
|
1150 |
|
|
DAC960_ProcessRequests(Controller);
|
1151 |
|
|
/*
|
1152 |
|
|
Release exclusive access to Controller.
|
1153 |
|
|
*/
|
1154 |
|
|
DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
|
1155 |
|
|
}
|
1156 |
|
|
|
1157 |
|
|
|
1158 |
|
|
/*
|
1159 |
|
|
DAC960_ReadWriteError prints an appropriate error message for Command when
|
1160 |
|
|
an error occurs on a read or write operation.
|
1161 |
|
|
*/
|
1162 |
|
|
|
1163 |
|
|
static void DAC960_ReadWriteError(DAC960_Command_T *Command)
|
1164 |
|
|
{
|
1165 |
|
|
DAC960_Controller_T *Controller = Command->Controller;
|
1166 |
|
|
char *CommandName = "UNKNOWN";
|
1167 |
|
|
switch (Command->CommandType)
|
1168 |
|
|
{
|
1169 |
|
|
case DAC960_ReadCommand:
|
1170 |
|
|
case DAC960_ReadRetryCommand:
|
1171 |
|
|
CommandName = "READ";
|
1172 |
|
|
break;
|
1173 |
|
|
case DAC960_WriteCommand:
|
1174 |
|
|
case DAC960_WriteRetryCommand:
|
1175 |
|
|
CommandName = "WRITE";
|
1176 |
|
|
break;
|
1177 |
|
|
case DAC960_MonitoringCommand:
|
1178 |
|
|
case DAC960_ImmediateCommand:
|
1179 |
|
|
break;
|
1180 |
|
|
}
|
1181 |
|
|
switch (Command->CommandStatus)
|
1182 |
|
|
{
|
1183 |
|
|
case DAC960_IrrecoverableDataError:
|
1184 |
|
|
DAC960_Error("Irrecoverable Data Error on %s:\n",
|
1185 |
|
|
Controller, CommandName);
|
1186 |
|
|
break;
|
1187 |
|
|
case DAC960_LogicalDriveNonexistentOrOffline:
|
1188 |
|
|
break;
|
1189 |
|
|
case DAC960_AccessBeyondEndOfLogicalDrive:
|
1190 |
|
|
DAC960_Error("Attempt to Access Beyond End of Logical Drive "
|
1191 |
|
|
"on %s:\n", Controller, CommandName);
|
1192 |
|
|
break;
|
1193 |
|
|
case DAC960_BadDataEncountered:
|
1194 |
|
|
DAC960_Error("Bad Data Encountered on %s:\n", Controller, CommandName);
|
1195 |
|
|
break;
|
1196 |
|
|
default:
|
1197 |
|
|
DAC960_Error("Unexpected Error Status %04X on %s:\n",
|
1198 |
|
|
Controller, Command->CommandStatus, CommandName);
|
1199 |
|
|
break;
|
1200 |
|
|
}
|
1201 |
|
|
DAC960_Error(" /dev/rd/c%dd%d: absolute blocks %d..%d\n",
|
1202 |
|
|
Controller, Controller->ControllerNumber,
|
1203 |
|
|
Command->LogicalDriveNumber, Command->BlockNumber,
|
1204 |
|
|
Command->BlockNumber + Command->BlockCount - 1);
|
1205 |
|
|
if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0)
|
1206 |
|
|
DAC960_Error(" /dev/rd/c%dd%dp%d: relative blocks %d..%d\n",
|
1207 |
|
|
Controller, Controller->ControllerNumber,
|
1208 |
|
|
Command->LogicalDriveNumber,
|
1209 |
|
|
DAC960_PartitionNumber(Command->BufferHeader->b_rdev),
|
1210 |
|
|
Command->BufferHeader->b_rsector,
|
1211 |
|
|
Command->BufferHeader->b_rsector + Command->BlockCount - 1);
|
1212 |
|
|
}
|
1213 |
|
|
|
1214 |
|
|
|
1215 |
|
|
/*
|
1216 |
|
|
DAC960_ProcessCompletedBuffer performs completion processing for an
|
1217 |
|
|
individual Buffer.
|
1218 |
|
|
*/
|
1219 |
|
|
|
1220 |
|
|
static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader,
|
1221 |
|
|
boolean SuccessfulIO)
|
1222 |
|
|
{
|
1223 |
|
|
mark_buffer_uptodate(BufferHeader, SuccessfulIO);
|
1224 |
|
|
unlock_buffer(BufferHeader);
|
1225 |
|
|
}
|
1226 |
|
|
|
1227 |
|
|
|
1228 |
|
|
/*
|
1229 |
|
|
DAC960_ProcessCompletedCommand performs completion processing for Command.
|
1230 |
|
|
*/
|
1231 |
|
|
|
1232 |
|
|
static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command)
|
1233 |
|
|
{
|
1234 |
|
|
DAC960_Controller_T *Controller = Command->Controller;
|
1235 |
|
|
DAC960_CommandType_T CommandType = Command->CommandType;
|
1236 |
|
|
DAC960_CommandStatus_T CommandStatus = Command->CommandStatus;
|
1237 |
|
|
BufferHeader_T *BufferHeader = Command->BufferHeader;
|
1238 |
|
|
if (CommandType == DAC960_ReadCommand ||
|
1239 |
|
|
CommandType == DAC960_WriteCommand)
|
1240 |
|
|
{
|
1241 |
|
|
if (CommandStatus == DAC960_NormalCompletion)
|
1242 |
|
|
{
|
1243 |
|
|
/*
|
1244 |
|
|
Perform completion processing for all buffers in this I/O Request.
|
1245 |
|
|
*/
|
1246 |
|
|
while (BufferHeader != NULL)
|
1247 |
|
|
{
|
1248 |
|
|
BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
|
1249 |
|
|
BufferHeader->b_reqnext = NULL;
|
1250 |
|
|
DAC960_ProcessCompletedBuffer(BufferHeader, true);
|
1251 |
|
|
BufferHeader = NextBufferHeader;
|
1252 |
|
|
}
|
1253 |
|
|
/*
|
1254 |
|
|
Wake up requestor for swap file paging requests.
|
1255 |
|
|
*/
|
1256 |
|
|
if (Command->Semaphore != NULL)
|
1257 |
|
|
{
|
1258 |
|
|
up(Command->Semaphore);
|
1259 |
|
|
Command->Semaphore = NULL;
|
1260 |
|
|
}
|
1261 |
|
|
}
|
1262 |
|
|
else if ((CommandStatus == DAC960_IrrecoverableDataError ||
|
1263 |
|
|
CommandStatus == DAC960_BadDataEncountered) &&
|
1264 |
|
|
BufferHeader != NULL &&
|
1265 |
|
|
BufferHeader->b_reqnext != NULL)
|
1266 |
|
|
{
|
1267 |
|
|
DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
|
1268 |
|
|
if (CommandType == DAC960_ReadCommand)
|
1269 |
|
|
{
|
1270 |
|
|
Command->CommandType = DAC960_ReadRetryCommand;
|
1271 |
|
|
CommandMailbox->Type5.CommandOpcode = DAC960_Read;
|
1272 |
|
|
}
|
1273 |
|
|
else
|
1274 |
|
|
{
|
1275 |
|
|
Command->CommandType = DAC960_WriteRetryCommand;
|
1276 |
|
|
CommandMailbox->Type5.CommandOpcode = DAC960_Write;
|
1277 |
|
|
}
|
1278 |
|
|
Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits;
|
1279 |
|
|
CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
|
1280 |
|
|
CommandMailbox->Type5.BusAddress =
|
1281 |
|
|
Virtual_to_Bus(BufferHeader->b_data);
|
1282 |
|
|
DAC960_QueueCommand(Command);
|
1283 |
|
|
return;
|
1284 |
|
|
}
|
1285 |
|
|
else
|
1286 |
|
|
{
|
1287 |
|
|
DAC960_ReadWriteError(Command);
|
1288 |
|
|
/*
|
1289 |
|
|
Perform completion processing for all buffers in this I/O Request.
|
1290 |
|
|
*/
|
1291 |
|
|
while (BufferHeader != NULL)
|
1292 |
|
|
{
|
1293 |
|
|
BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
|
1294 |
|
|
BufferHeader->b_reqnext = NULL;
|
1295 |
|
|
DAC960_ProcessCompletedBuffer(BufferHeader, false);
|
1296 |
|
|
BufferHeader = NextBufferHeader;
|
1297 |
|
|
}
|
1298 |
|
|
/*
|
1299 |
|
|
Wake up requestor for swap file paging requests.
|
1300 |
|
|
*/
|
1301 |
|
|
if (Command->Semaphore != NULL)
|
1302 |
|
|
{
|
1303 |
|
|
up(Command->Semaphore);
|
1304 |
|
|
Command->Semaphore = NULL;
|
1305 |
|
|
}
|
1306 |
|
|
}
|
1307 |
|
|
}
|
1308 |
|
|
else if (CommandType == DAC960_ReadRetryCommand ||
|
1309 |
|
|
CommandType == DAC960_WriteRetryCommand)
|
1310 |
|
|
{
|
1311 |
|
|
BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
|
1312 |
|
|
BufferHeader->b_reqnext = NULL;
|
1313 |
|
|
/*
|
1314 |
|
|
Perform completion processing for this single buffer.
|
1315 |
|
|
*/
|
1316 |
|
|
if (CommandStatus == DAC960_NormalCompletion)
|
1317 |
|
|
DAC960_ProcessCompletedBuffer(BufferHeader, true);
|
1318 |
|
|
else
|
1319 |
|
|
{
|
1320 |
|
|
DAC960_ReadWriteError(Command);
|
1321 |
|
|
DAC960_ProcessCompletedBuffer(BufferHeader, false);
|
1322 |
|
|
}
|
1323 |
|
|
if (NextBufferHeader != NULL)
|
1324 |
|
|
{
|
1325 |
|
|
DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
|
1326 |
|
|
Command->BlockNumber +=
|
1327 |
|
|
BufferHeader->b_size >> DAC960_BlockSizeBits;
|
1328 |
|
|
Command->BlockCount =
|
1329 |
|
|
NextBufferHeader->b_size >> DAC960_BlockSizeBits;
|
1330 |
|
|
Command->BufferHeader = NextBufferHeader;
|
1331 |
|
|
CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
|
1332 |
|
|
CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
|
1333 |
|
|
CommandMailbox->Type5.BusAddress =
|
1334 |
|
|
Virtual_to_Bus(NextBufferHeader->b_data);
|
1335 |
|
|
DAC960_QueueCommand(Command);
|
1336 |
|
|
return;
|
1337 |
|
|
}
|
1338 |
|
|
}
|
1339 |
|
|
else if (CommandType == DAC960_MonitoringCommand)
|
1340 |
|
|
{
|
1341 |
|
|
DAC960_CommandOpcode_T CommandOpcode =
|
1342 |
|
|
Command->CommandMailbox.Common.CommandOpcode;
|
1343 |
|
|
unsigned int OldCriticalLogicalDriveCount = 0;
|
1344 |
|
|
unsigned int NewCriticalLogicalDriveCount = 0;
|
1345 |
|
|
if (CommandOpcode == DAC960_Enquiry)
|
1346 |
|
|
{
|
1347 |
|
|
DAC960_Enquiry_T *OldEnquiry =
|
1348 |
|
|
&Controller->Enquiry[Controller->EnquiryIndex];
|
1349 |
|
|
DAC960_Enquiry_T *NewEnquiry =
|
1350 |
|
|
&Controller->Enquiry[Controller->EnquiryIndex ^= 1];
|
1351 |
|
|
OldCriticalLogicalDriveCount = OldEnquiry->CriticalLogicalDriveCount;
|
1352 |
|
|
NewCriticalLogicalDriveCount = NewEnquiry->CriticalLogicalDriveCount;
|
1353 |
|
|
if (NewEnquiry->StatusFlags.DeferredWriteError !=
|
1354 |
|
|
OldEnquiry->StatusFlags.DeferredWriteError)
|
1355 |
|
|
DAC960_Critical("Deferred Write Error Flag is now %s\n", Controller,
|
1356 |
|
|
(NewEnquiry->StatusFlags.DeferredWriteError
|
1357 |
|
|
? "TRUE" : "FALSE"));
|
1358 |
|
|
if ((NewCriticalLogicalDriveCount > 0 ||
|
1359 |
|
|
NewCriticalLogicalDriveCount != OldCriticalLogicalDriveCount) ||
|
1360 |
|
|
(NewEnquiry->OfflineLogicalDriveCount > 0 ||
|
1361 |
|
|
NewEnquiry->OfflineLogicalDriveCount !=
|
1362 |
|
|
OldEnquiry->OfflineLogicalDriveCount) ||
|
1363 |
|
|
(NewEnquiry->DeadDriveCount > 0 ||
|
1364 |
|
|
NewEnquiry->DeadDriveCount !=
|
1365 |
|
|
OldEnquiry->DeadDriveCount) ||
|
1366 |
|
|
(NewEnquiry->EventLogSequenceNumber !=
|
1367 |
|
|
OldEnquiry->EventLogSequenceNumber) ||
|
1368 |
|
|
(jiffies - Controller->SecondaryMonitoringTime
|
1369 |
|
|
>= DAC960_SecondaryMonitoringInterval))
|
1370 |
|
|
{
|
1371 |
|
|
Controller->NeedLogicalDriveInformation = true;
|
1372 |
|
|
Controller->NewEventLogSequenceNumber =
|
1373 |
|
|
NewEnquiry->EventLogSequenceNumber;
|
1374 |
|
|
Controller->NeedDeviceStateInformation = true;
|
1375 |
|
|
Controller->DeviceStateChannel = 0;
|
1376 |
|
|
Controller->DeviceStateTargetID = 0;
|
1377 |
|
|
Controller->SecondaryMonitoringTime = jiffies;
|
1378 |
|
|
}
|
1379 |
|
|
if ((NewEnquiry->RebuildCount > 0 &&
|
1380 |
|
|
jiffies - Controller->RebuildLastReportTime
|
1381 |
|
|
>= DAC960_RebuildStatusReportingInterval) ||
|
1382 |
|
|
NewEnquiry->RebuildCount != OldEnquiry->RebuildCount)
|
1383 |
|
|
Controller->NeedRebuildProgress = true;
|
1384 |
|
|
}
|
1385 |
|
|
else if (CommandOpcode == DAC960_GetLogicalDriveInformation)
|
1386 |
|
|
{
|
1387 |
|
|
int LogicalDriveNumber;
|
1388 |
|
|
for (LogicalDriveNumber = 0;
|
1389 |
|
|
LogicalDriveNumber < Controller->LogicalDriveCount;
|
1390 |
|
|
LogicalDriveNumber++)
|
1391 |
|
|
{
|
1392 |
|
|
DAC960_LogicalDriveInformation_T *OldLogicalDriveInformation =
|
1393 |
|
|
&Controller->LogicalDriveInformation
|
1394 |
|
|
[Controller->LogicalDriveInformationIndex]
|
1395 |
|
|
[LogicalDriveNumber];
|
1396 |
|
|
DAC960_LogicalDriveInformation_T *NewLogicalDriveInformation =
|
1397 |
|
|
&Controller->LogicalDriveInformation
|
1398 |
|
|
[Controller->LogicalDriveInformationIndex ^ 1]
|
1399 |
|
|
[LogicalDriveNumber];
|
1400 |
|
|
if (NewLogicalDriveInformation->LogicalDriveState !=
|
1401 |
|
|
OldLogicalDriveInformation->LogicalDriveState)
|
1402 |
|
|
DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
|
1403 |
|
|
"is now %s\n", Controller,
|
1404 |
|
|
LogicalDriveNumber,
|
1405 |
|
|
Controller->ControllerNumber,
|
1406 |
|
|
LogicalDriveNumber,
|
1407 |
|
|
(NewLogicalDriveInformation->LogicalDriveState
|
1408 |
|
|
== DAC960_LogicalDrive_Online
|
1409 |
|
|
? "ONLINE"
|
1410 |
|
|
: NewLogicalDriveInformation->LogicalDriveState
|
1411 |
|
|
== DAC960_LogicalDrive_Critical
|
1412 |
|
|
? "CRITICAL" : "OFFLINE"));
|
1413 |
|
|
if (NewLogicalDriveInformation->WriteBack !=
|
1414 |
|
|
OldLogicalDriveInformation->WriteBack)
|
1415 |
|
|
DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
|
1416 |
|
|
"is now %s\n", Controller,
|
1417 |
|
|
LogicalDriveNumber,
|
1418 |
|
|
Controller->ControllerNumber,
|
1419 |
|
|
LogicalDriveNumber,
|
1420 |
|
|
(NewLogicalDriveInformation->WriteBack
|
1421 |
|
|
? "WRITE BACK" : "WRITE THRU"));
|
1422 |
|
|
}
|
1423 |
|
|
Controller->LogicalDriveInformationIndex ^= 1;
|
1424 |
|
|
}
|
1425 |
|
|
else if (CommandOpcode == DAC960_PerformEventLogOperation)
|
1426 |
|
|
{
|
1427 |
|
|
DAC960_EventLogEntry_T *EventLogEntry = &Controller->EventLogEntry;
|
1428 |
|
|
if (EventLogEntry->SequenceNumber ==
|
1429 |
|
|
Controller->OldEventLogSequenceNumber)
|
1430 |
|
|
{
|
1431 |
|
|
unsigned char SenseKey = EventLogEntry->SenseKey;
|
1432 |
|
|
unsigned char AdditionalSenseCode =
|
1433 |
|
|
EventLogEntry->AdditionalSenseCode;
|
1434 |
|
|
unsigned char AdditionalSenseCodeQualifier =
|
1435 |
|
|
EventLogEntry->AdditionalSenseCodeQualifier;
|
1436 |
|
|
if (SenseKey == 9 &&
|
1437 |
|
|
AdditionalSenseCode == 0x80 &&
|
1438 |
|
|
AdditionalSenseCodeQualifier < DAC960_EventMessagesCount)
|
1439 |
|
|
DAC960_Critical("Physical Drive %d:%d %s\n", Controller,
|
1440 |
|
|
EventLogEntry->Channel,
|
1441 |
|
|
EventLogEntry->TargetID,
|
1442 |
|
|
DAC960_EventMessages[
|
1443 |
|
|
AdditionalSenseCodeQualifier]);
|
1444 |
|
|
else if (!((SenseKey == 2 &&
|
1445 |
|
|
AdditionalSenseCode == 0x04 &&
|
1446 |
|
|
(AdditionalSenseCodeQualifier == 0x01 ||
|
1447 |
|
|
AdditionalSenseCodeQualifier == 0x02)) ||
|
1448 |
|
|
(SenseKey == 6 && AdditionalSenseCode == 0x29)))
|
1449 |
|
|
DAC960_Critical("Physical Drive %d:%d Error Log: "
|
1450 |
|
|
"Sense Key = %d, ASC = %02X, ASCQ = %02X\n",
|
1451 |
|
|
Controller,
|
1452 |
|
|
EventLogEntry->Channel,
|
1453 |
|
|
EventLogEntry->TargetID,
|
1454 |
|
|
SenseKey,
|
1455 |
|
|
AdditionalSenseCode,
|
1456 |
|
|
AdditionalSenseCodeQualifier);
|
1457 |
|
|
}
|
1458 |
|
|
Controller->OldEventLogSequenceNumber++;
|
1459 |
|
|
}
|
1460 |
|
|
else if (CommandOpcode == DAC960_GetDeviceState)
|
1461 |
|
|
{
|
1462 |
|
|
DAC960_DeviceState_T *OldDeviceState =
|
1463 |
|
|
&Controller->DeviceState[Controller->DeviceStateIndex]
|
1464 |
|
|
[Controller->DeviceStateChannel]
|
1465 |
|
|
[Controller->DeviceStateTargetID];
|
1466 |
|
|
DAC960_DeviceState_T *NewDeviceState =
|
1467 |
|
|
&Controller->DeviceState[Controller->DeviceStateIndex ^ 1]
|
1468 |
|
|
[Controller->DeviceStateChannel]
|
1469 |
|
|
[Controller->DeviceStateTargetID];
|
1470 |
|
|
if (NewDeviceState->DeviceState != OldDeviceState->DeviceState)
|
1471 |
|
|
DAC960_Critical("Physical Drive %d:%d is now %s\n", Controller,
|
1472 |
|
|
Controller->DeviceStateChannel,
|
1473 |
|
|
Controller->DeviceStateTargetID,
|
1474 |
|
|
(NewDeviceState->DeviceState == DAC960_Device_Dead
|
1475 |
|
|
? "DEAD"
|
1476 |
|
|
: NewDeviceState->DeviceState
|
1477 |
|
|
== DAC960_Device_WriteOnly
|
1478 |
|
|
? "WRITE-ONLY"
|
1479 |
|
|
: NewDeviceState->DeviceState
|
1480 |
|
|
== DAC960_Device_Online
|
1481 |
|
|
? "ONLINE" : "STANDBY"));
|
1482 |
|
|
if (++Controller->DeviceStateTargetID == DAC960_MaxTargets)
|
1483 |
|
|
{
|
1484 |
|
|
Controller->DeviceStateChannel++;
|
1485 |
|
|
Controller->DeviceStateTargetID = 0;
|
1486 |
|
|
}
|
1487 |
|
|
}
|
1488 |
|
|
else if (CommandOpcode == DAC960_GetRebuildProgress)
|
1489 |
|
|
{
|
1490 |
|
|
unsigned int LogicalDriveNumber =
|
1491 |
|
|
Controller->RebuildProgress.LogicalDriveNumber;
|
1492 |
|
|
unsigned int LogicalDriveSize =
|
1493 |
|
|
Controller->RebuildProgress.LogicalDriveSize;
|
1494 |
|
|
unsigned int BlocksCompleted =
|
1495 |
|
|
LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks;
|
1496 |
|
|
switch (CommandStatus)
|
1497 |
|
|
{
|
1498 |
|
|
case DAC960_NormalCompletion:
|
1499 |
|
|
DAC960_Critical("REBUILD IN PROGRESS: "
|
1500 |
|
|
"Logical Drive %d (/dev/rd/c%dd%d) "
|
1501 |
|
|
"%d%% completed\n",
|
1502 |
|
|
Controller, LogicalDriveNumber,
|
1503 |
|
|
Controller->ControllerNumber,
|
1504 |
|
|
LogicalDriveNumber,
|
1505 |
|
|
(100 * (BlocksCompleted >> 7))
|
1506 |
|
|
/ (LogicalDriveSize >> 7));
|
1507 |
|
|
break;
|
1508 |
|
|
case DAC960_RebuildFailed_LogicalDriveFailure:
|
1509 |
|
|
DAC960_Critical("REBUILD FAILED due to "
|
1510 |
|
|
"LOGICAL DRIVE FAILURE\n", Controller);
|
1511 |
|
|
break;
|
1512 |
|
|
case DAC960_RebuildFailed_BadBlocksOnOther:
|
1513 |
|
|
DAC960_Critical("REBUILD FAILED due to "
|
1514 |
|
|
"BAD BLOCKS ON OTHER DRIVES\n", Controller);
|
1515 |
|
|
break;
|
1516 |
|
|
case DAC960_RebuildFailed_NewDriveFailed:
|
1517 |
|
|
DAC960_Critical("REBUILD FAILED due to "
|
1518 |
|
|
"FAILURE OF DRIVE BEING REBUILT\n", Controller);
|
1519 |
|
|
break;
|
1520 |
|
|
case DAC960_RebuildSuccessful:
|
1521 |
|
|
DAC960_Critical("REBUILD COMPLETED SUCCESSFULLY\n", Controller);
|
1522 |
|
|
break;
|
1523 |
|
|
case DAC960_NoRebuildOrCheckInProgress:
|
1524 |
|
|
break;
|
1525 |
|
|
}
|
1526 |
|
|
Controller->RebuildLastReportTime = jiffies;
|
1527 |
|
|
}
|
1528 |
|
|
if (Controller->NeedLogicalDriveInformation &&
|
1529 |
|
|
NewCriticalLogicalDriveCount >= OldCriticalLogicalDriveCount)
|
1530 |
|
|
{
|
1531 |
|
|
Controller->NeedLogicalDriveInformation = false;
|
1532 |
|
|
Command->CommandMailbox.Type3.CommandOpcode =
|
1533 |
|
|
DAC960_GetLogicalDriveInformation;
|
1534 |
|
|
Command->CommandMailbox.Type3.BusAddress =
|
1535 |
|
|
Virtual_to_Bus(
|
1536 |
|
|
&Controller->LogicalDriveInformation
|
1537 |
|
|
[Controller->LogicalDriveInformationIndex ^ 1]);
|
1538 |
|
|
DAC960_QueueCommand(Command);
|
1539 |
|
|
return;
|
1540 |
|
|
}
|
1541 |
|
|
if (Controller->NewEventLogSequenceNumber
|
1542 |
|
|
- Controller->OldEventLogSequenceNumber > 0)
|
1543 |
|
|
{
|
1544 |
|
|
Command->CommandMailbox.Type3E.CommandOpcode =
|
1545 |
|
|
DAC960_PerformEventLogOperation;
|
1546 |
|
|
Command->CommandMailbox.Type3E.OperationType =
|
1547 |
|
|
DAC960_GetEventLogEntry;
|
1548 |
|
|
Command->CommandMailbox.Type3E.OperationQualifier = 1;
|
1549 |
|
|
Command->CommandMailbox.Type3E.SequenceNumber =
|
1550 |
|
|
Controller->OldEventLogSequenceNumber;
|
1551 |
|
|
Command->CommandMailbox.Type3E.BusAddress =
|
1552 |
|
|
Virtual_to_Bus(&Controller->EventLogEntry);
|
1553 |
|
|
DAC960_QueueCommand(Command);
|
1554 |
|
|
return;
|
1555 |
|
|
}
|
1556 |
|
|
if (Controller->NeedDeviceStateInformation)
|
1557 |
|
|
{
|
1558 |
|
|
while (Controller->DeviceStateChannel < Controller->Channels)
|
1559 |
|
|
{
|
1560 |
|
|
DAC960_DeviceState_T *OldDeviceState =
|
1561 |
|
|
&Controller->DeviceState[Controller->DeviceStateIndex]
|
1562 |
|
|
[Controller->DeviceStateChannel]
|
1563 |
|
|
[Controller->DeviceStateTargetID];
|
1564 |
|
|
if (OldDeviceState->Present &&
|
1565 |
|
|
OldDeviceState->DeviceType == DAC960_DiskType)
|
1566 |
|
|
{
|
1567 |
|
|
Command->CommandMailbox.Type3D.CommandOpcode =
|
1568 |
|
|
DAC960_GetDeviceState;
|
1569 |
|
|
Command->CommandMailbox.Type3D.Channel =
|
1570 |
|
|
Controller->DeviceStateChannel;
|
1571 |
|
|
Command->CommandMailbox.Type3D.TargetID =
|
1572 |
|
|
Controller->DeviceStateTargetID;
|
1573 |
|
|
Command->CommandMailbox.Type3D.BusAddress =
|
1574 |
|
|
Virtual_to_Bus(&Controller->DeviceState
|
1575 |
|
|
[Controller->DeviceStateIndex ^ 1]
|
1576 |
|
|
[Controller->DeviceStateChannel]
|
1577 |
|
|
[Controller->DeviceStateTargetID]);
|
1578 |
|
|
DAC960_QueueCommand(Command);
|
1579 |
|
|
return;
|
1580 |
|
|
}
|
1581 |
|
|
if (++Controller->DeviceStateTargetID == DAC960_MaxTargets)
|
1582 |
|
|
{
|
1583 |
|
|
Controller->DeviceStateChannel++;
|
1584 |
|
|
Controller->DeviceStateTargetID = 0;
|
1585 |
|
|
}
|
1586 |
|
|
}
|
1587 |
|
|
Controller->NeedDeviceStateInformation = false;
|
1588 |
|
|
Controller->DeviceStateIndex ^= 1;
|
1589 |
|
|
}
|
1590 |
|
|
if (Controller->NeedRebuildProgress)
|
1591 |
|
|
{
|
1592 |
|
|
Controller->NeedRebuildProgress = false;
|
1593 |
|
|
Command->CommandMailbox.Type3.CommandOpcode =
|
1594 |
|
|
DAC960_GetRebuildProgress;
|
1595 |
|
|
Command->CommandMailbox.Type3.BusAddress =
|
1596 |
|
|
Virtual_to_Bus(&Controller->RebuildProgress);
|
1597 |
|
|
DAC960_QueueCommand(Command);
|
1598 |
|
|
return;
|
1599 |
|
|
}
|
1600 |
|
|
if (Controller->NeedLogicalDriveInformation &&
|
1601 |
|
|
NewCriticalLogicalDriveCount < OldCriticalLogicalDriveCount)
|
1602 |
|
|
{
|
1603 |
|
|
Controller->NeedLogicalDriveInformation = false;
|
1604 |
|
|
Command->CommandMailbox.Type3.CommandOpcode =
|
1605 |
|
|
DAC960_GetLogicalDriveInformation;
|
1606 |
|
|
Command->CommandMailbox.Type3.BusAddress =
|
1607 |
|
|
Virtual_to_Bus(
|
1608 |
|
|
&Controller->LogicalDriveInformation
|
1609 |
|
|
[Controller->LogicalDriveInformationIndex ^ 1]);
|
1610 |
|
|
DAC960_QueueCommand(Command);
|
1611 |
|
|
return;
|
1612 |
|
|
}
|
1613 |
|
|
Controller->MonitoringTimer.expires =
|
1614 |
|
|
jiffies + DAC960_MonitoringTimerInterval;
|
1615 |
|
|
add_timer(&Controller->MonitoringTimer);
|
1616 |
|
|
}
|
1617 |
|
|
else if (CommandType == DAC960_ImmediateCommand)
|
1618 |
|
|
{
|
1619 |
|
|
up(Command->Semaphore);
|
1620 |
|
|
Command->Semaphore = NULL;
|
1621 |
|
|
return;
|
1622 |
|
|
}
|
1623 |
|
|
else panic("DAC960: Unknown Command Type %d\n", CommandType);
|
1624 |
|
|
/*
|
1625 |
|
|
Queue a Monitoring Command to the Controller using the just completed
|
1626 |
|
|
Command if one was deferred previously due to lack of a free Command when
|
1627 |
|
|
the Monitoring Timer Function was called.
|
1628 |
|
|
*/
|
1629 |
|
|
if (Controller->MonitoringCommandDeferred)
|
1630 |
|
|
{
|
1631 |
|
|
Controller->MonitoringCommandDeferred = false;
|
1632 |
|
|
DAC960_QueueMonitoringCommand(Command);
|
1633 |
|
|
return;
|
1634 |
|
|
}
|
1635 |
|
|
/*
|
1636 |
|
|
Attempt to remove a new I/O Request from the Controller's I/O Request
|
1637 |
|
|
Queue and queue it to the Controller using the just completed Command.
|
1638 |
|
|
If there is no I/O Request to be queued, deallocate the Command.
|
1639 |
|
|
*/
|
1640 |
|
|
if (!DAC960_ProcessRequest(Controller, Command))
|
1641 |
|
|
DAC960_DeallocateCommand(Command);
|
1642 |
|
|
}
|
1643 |
|
|
|
1644 |
|
|
|
1645 |
|
|
/*
|
1646 |
|
|
DAC960_InterruptHandler handles hardware interrupts from DAC960 Controllers.
|
1647 |
|
|
*/
|
1648 |
|
|
|
1649 |
|
|
static void DAC960_InterruptHandler(int IRQ_Channel,
|
1650 |
|
|
void *DeviceIdentifier,
|
1651 |
|
|
Registers_T *InterruptRegisters)
|
1652 |
|
|
{
|
1653 |
|
|
DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
|
1654 |
|
|
void *ControllerBaseAddress = Controller->BaseAddress;
|
1655 |
|
|
DAC960_V4_StatusMailbox_T *NextStatusMailbox;
|
1656 |
|
|
ProcessorFlags_T ProcessorFlags;
|
1657 |
|
|
/*
|
1658 |
|
|
Acquire exclusive access to Controller.
|
1659 |
|
|
*/
|
1660 |
|
|
DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags);
|
1661 |
|
|
/*
|
1662 |
|
|
Process Hardware Interrupts for Controller.
|
1663 |
|
|
*/
|
1664 |
|
|
switch (Controller->ControllerType)
|
1665 |
|
|
{
|
1666 |
|
|
case DAC960_V4_Controller:
|
1667 |
|
|
DAC960_V4_AcknowledgeInterrupt(ControllerBaseAddress);
|
1668 |
|
|
NextStatusMailbox = Controller->NextStatusMailbox;
|
1669 |
|
|
while (NextStatusMailbox->Fields.Valid)
|
1670 |
|
|
{
|
1671 |
|
|
DAC960_CommandIdentifier_T CommandIdentifier =
|
1672 |
|
|
NextStatusMailbox->Fields.CommandIdentifier;
|
1673 |
|
|
DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier];
|
1674 |
|
|
Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus;
|
1675 |
|
|
NextStatusMailbox->Word = 0;
|
1676 |
|
|
if (++NextStatusMailbox > Controller->LastStatusMailbox)
|
1677 |
|
|
NextStatusMailbox = Controller->FirstStatusMailbox;
|
1678 |
|
|
DAC960_ProcessCompletedCommand(Command);
|
1679 |
|
|
}
|
1680 |
|
|
Controller->NextStatusMailbox = NextStatusMailbox;
|
1681 |
|
|
break;
|
1682 |
|
|
case DAC960_V3_Controller:
|
1683 |
|
|
while (DAC960_V3_StatusAvailableP(ControllerBaseAddress))
|
1684 |
|
|
{
|
1685 |
|
|
DAC960_CommandIdentifier_T CommandIdentifier =
|
1686 |
|
|
DAC960_V3_ReadStatusCommandIdentifier(ControllerBaseAddress);
|
1687 |
|
|
DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier];
|
1688 |
|
|
Command->CommandStatus =
|
1689 |
|
|
DAC960_V3_ReadStatusRegister(ControllerBaseAddress);
|
1690 |
|
|
DAC960_V3_AcknowledgeInterrupt(ControllerBaseAddress);
|
1691 |
|
|
DAC960_V3_AcknowledgeStatus(ControllerBaseAddress);
|
1692 |
|
|
DAC960_ProcessCompletedCommand(Command);
|
1693 |
|
|
}
|
1694 |
|
|
break;
|
1695 |
|
|
}
|
1696 |
|
|
/*
|
1697 |
|
|
Attempt to remove additional I/O Requests from the Controller's
|
1698 |
|
|
I/O Request Queue and queue them to the Controller.
|
1699 |
|
|
*/
|
1700 |
|
|
DAC960_ProcessRequests(Controller);
|
1701 |
|
|
/*
|
1702 |
|
|
Release exclusive access to Controller.
|
1703 |
|
|
*/
|
1704 |
|
|
DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags);
|
1705 |
|
|
}
|
1706 |
|
|
|
1707 |
|
|
|
1708 |
|
|
/*
|
1709 |
|
|
DAC960_QueueMonitoringCommand queues a Monitoring Command to Controller.
|
1710 |
|
|
*/
|
1711 |
|
|
|
1712 |
|
|
static void DAC960_QueueMonitoringCommand(DAC960_Command_T *Command)
|
1713 |
|
|
{
|
1714 |
|
|
DAC960_Controller_T *Controller = Command->Controller;
|
1715 |
|
|
DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
|
1716 |
|
|
DAC960_ClearCommand(Command);
|
1717 |
|
|
Command->CommandType = DAC960_MonitoringCommand;
|
1718 |
|
|
CommandMailbox->Type3.CommandOpcode = DAC960_Enquiry;
|
1719 |
|
|
CommandMailbox->Type3.BusAddress =
|
1720 |
|
|
Virtual_to_Bus(&Controller->Enquiry[Controller->EnquiryIndex ^ 1]);
|
1721 |
|
|
DAC960_QueueCommand(Command);
|
1722 |
|
|
}
|
1723 |
|
|
|
1724 |
|
|
|
1725 |
|
|
/*
|
1726 |
|
|
DAC960_MonitoringTimerFunction is the timer function for monitoring
|
1727 |
|
|
the status of DAC960 Controllers.
|
1728 |
|
|
*/
|
1729 |
|
|
|
1730 |
|
|
static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
|
1731 |
|
|
{
|
1732 |
|
|
DAC960_Controller_T *Controller = (DAC960_Controller_T *) TimerData;
|
1733 |
|
|
DAC960_Command_T *Command;
|
1734 |
|
|
ProcessorFlags_T ProcessorFlags;
|
1735 |
|
|
/*
|
1736 |
|
|
Acquire exclusive access to Controller.
|
1737 |
|
|
*/
|
1738 |
|
|
DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
|
1739 |
|
|
/*
|
1740 |
|
|
Queue a Status Monitoring Command for Controller;
|
1741 |
|
|
*/
|
1742 |
|
|
Command = DAC960_AllocateCommand(Controller);
|
1743 |
|
|
if (Command != NULL)
|
1744 |
|
|
DAC960_QueueMonitoringCommand(Command);
|
1745 |
|
|
else Controller->MonitoringCommandDeferred = true;
|
1746 |
|
|
/*
|
1747 |
|
|
Release exclusive access to Controller.
|
1748 |
|
|
*/
|
1749 |
|
|
DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
|
1750 |
|
|
}
|
1751 |
|
|
|
1752 |
|
|
|
1753 |
|
|
/*
|
1754 |
|
|
DAC960_Open is the Device Open Function for the DAC960 Driver.
|
1755 |
|
|
*/
|
1756 |
|
|
|
1757 |
|
|
static int DAC960_Open(Inode_T *Inode, File_T *File)
|
1758 |
|
|
{
|
1759 |
|
|
int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
|
1760 |
|
|
int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
|
1761 |
|
|
DAC960_Controller_T *Controller;
|
1762 |
|
|
if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1)
|
1763 |
|
|
return -ENXIO;
|
1764 |
|
|
Controller = DAC960_Controllers[ControllerNumber];
|
1765 |
|
|
if (Controller == NULL ||
|
1766 |
|
|
LogicalDriveNumber > Controller->LogicalDriveCount - 1)
|
1767 |
|
|
return -ENXIO;
|
1768 |
|
|
if (Controller->LogicalDriveInformation
|
1769 |
|
|
[Controller->LogicalDriveInformationIndex]
|
1770 |
|
|
[LogicalDriveNumber] .LogicalDriveState
|
1771 |
|
|
== DAC960_LogicalDrive_Offline)
|
1772 |
|
|
return -ENXIO;
|
1773 |
|
|
if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0)
|
1774 |
|
|
return -ENXIO;
|
1775 |
|
|
/*
|
1776 |
|
|
Increment Controller and Logical Drive Usage Counts.
|
1777 |
|
|
*/
|
1778 |
|
|
Controller->ControllerUsageCount++;
|
1779 |
|
|
Controller->LogicalDriveUsageCount[LogicalDriveNumber]++;
|
1780 |
|
|
return 0;
|
1781 |
|
|
}
|
1782 |
|
|
|
1783 |
|
|
|
1784 |
|
|
/*
|
1785 |
|
|
DAC960_Release is the Device Release Function for the DAC960 Driver.
|
1786 |
|
|
*/
|
1787 |
|
|
|
1788 |
|
|
static void DAC960_Release(Inode_T *Inode, File_T *File)
|
1789 |
|
|
{
|
1790 |
|
|
int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
|
1791 |
|
|
int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
|
1792 |
|
|
DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
|
1793 |
|
|
/*
|
1794 |
|
|
Force any buffered data to be written.
|
1795 |
|
|
*/
|
1796 |
|
|
fsync_dev(Inode->i_rdev);
|
1797 |
|
|
/*
|
1798 |
|
|
Decrement the Logical Drive and Controller Usage Counts.
|
1799 |
|
|
*/
|
1800 |
|
|
Controller->LogicalDriveUsageCount[LogicalDriveNumber]--;
|
1801 |
|
|
Controller->ControllerUsageCount--;
|
1802 |
|
|
}
|
1803 |
|
|
|
1804 |
|
|
|
1805 |
|
|
/*
|
1806 |
|
|
DAC960_Ioctl is the Device Ioctl Function for the DAC960 Driver.
|
1807 |
|
|
*/
|
1808 |
|
|
|
1809 |
|
|
static int DAC960_Ioctl(Inode_T *Inode, File_T *File,
|
1810 |
|
|
unsigned int Request, unsigned long Argument)
|
1811 |
|
|
{
|
1812 |
|
|
int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
|
1813 |
|
|
int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
|
1814 |
|
|
int PartitionNumber, ErrorCode;
|
1815 |
|
|
unsigned short Cylinders;
|
1816 |
|
|
DiskGeometry_T *Geometry;
|
1817 |
|
|
DAC960_Controller_T *Controller;
|
1818 |
|
|
if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1)
|
1819 |
|
|
return -ENXIO;
|
1820 |
|
|
Controller = DAC960_Controllers[ControllerNumber];
|
1821 |
|
|
if (Controller == NULL ||
|
1822 |
|
|
LogicalDriveNumber > Controller->LogicalDriveCount - 1)
|
1823 |
|
|
return -ENXIO;
|
1824 |
|
|
switch (Request)
|
1825 |
|
|
{
|
1826 |
|
|
case HDIO_GETGEO:
|
1827 |
|
|
/* Get BIOS Disk Geometry. */
|
1828 |
|
|
Geometry = (DiskGeometry_T *) Argument;
|
1829 |
|
|
if (Geometry == NULL) return -EINVAL;
|
1830 |
|
|
ErrorCode = verify_area(VERIFY_WRITE, Geometry, sizeof(DiskGeometry_T));
|
1831 |
|
|
if (ErrorCode != 0) return ErrorCode;
|
1832 |
|
|
Cylinders =
|
1833 |
|
|
Controller->LogicalDriveInformation
|
1834 |
|
|
[Controller->LogicalDriveInformationIndex]
|
1835 |
|
|
[LogicalDriveNumber].LogicalDriveSize
|
1836 |
|
|
/ (Controller->GeometryTranslationHeads *
|
1837 |
|
|
Controller->GeometryTranslationSectors);
|
1838 |
|
|
put_user(Controller->GeometryTranslationHeads, &Geometry->heads);
|
1839 |
|
|
put_user(Controller->GeometryTranslationSectors, &Geometry->sectors);
|
1840 |
|
|
put_user(Cylinders, &Geometry->cylinders);
|
1841 |
|
|
put_user(Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)]
|
1842 |
|
|
.start_sect, &Geometry->start);
|
1843 |
|
|
return 0;
|
1844 |
|
|
case BLKGETSIZE:
|
1845 |
|
|
/* Get Device Size. */
|
1846 |
|
|
if ((long *) Argument == NULL) return -EINVAL;
|
1847 |
|
|
ErrorCode = verify_area(VERIFY_WRITE, (long *) Argument, sizeof(long));
|
1848 |
|
|
if (ErrorCode != 0) return ErrorCode;
|
1849 |
|
|
put_user(Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)].nr_sects,
|
1850 |
|
|
(long *) Argument);
|
1851 |
|
|
return 0;
|
1852 |
|
|
case BLKRAGET:
|
1853 |
|
|
/* Get Read-Ahead. */
|
1854 |
|
|
if ((int *) Argument == NULL) return -EINVAL;
|
1855 |
|
|
ErrorCode = verify_area(VERIFY_WRITE, (int *) Argument, sizeof(int));
|
1856 |
|
|
if (ErrorCode != 0) return ErrorCode;
|
1857 |
|
|
put_user(read_ahead[MAJOR(Inode->i_rdev)], (int *) Argument);
|
1858 |
|
|
return 0;
|
1859 |
|
|
case BLKRASET:
|
1860 |
|
|
/* Set Read-Ahead. */
|
1861 |
|
|
if (!suser()) return -EACCES;
|
1862 |
|
|
if (Argument > 256) return -EINVAL;
|
1863 |
|
|
read_ahead[MAJOR(Inode->i_rdev)] = Argument;
|
1864 |
|
|
return 0;
|
1865 |
|
|
case BLKFLSBUF:
|
1866 |
|
|
/* Flush Buffers. */
|
1867 |
|
|
if (!suser()) return -EACCES;
|
1868 |
|
|
fsync_dev(Inode->i_rdev);
|
1869 |
|
|
invalidate_buffers(Inode->i_rdev);
|
1870 |
|
|
return 0;
|
1871 |
|
|
case BLKRRPART:
|
1872 |
|
|
/* Re-Read Partition Table. */
|
1873 |
|
|
if (!suser()) return -EACCES;
|
1874 |
|
|
if (Controller->LogicalDriveUsageCount[LogicalDriveNumber] > 1)
|
1875 |
|
|
return -EBUSY;
|
1876 |
|
|
for (PartitionNumber = 0;
|
1877 |
|
|
PartitionNumber < DAC960_MaxPartitions;
|
1878 |
|
|
PartitionNumber++)
|
1879 |
|
|
{
|
1880 |
|
|
KernelDevice_T Device = DAC960_KernelDevice(ControllerNumber,
|
1881 |
|
|
LogicalDriveNumber,
|
1882 |
|
|
PartitionNumber);
|
1883 |
|
|
int MinorNumber = DAC960_MinorNumber(LogicalDriveNumber,
|
1884 |
|
|
PartitionNumber);
|
1885 |
|
|
if (Controller->GenericDiskInfo.part[MinorNumber].nr_sects == 0)
|
1886 |
|
|
continue;
|
1887 |
|
|
/*
|
1888 |
|
|
Flush all changes and invalidate buffered state.
|
1889 |
|
|
*/
|
1890 |
|
|
sync_dev(Device);
|
1891 |
|
|
invalidate_inodes(Device);
|
1892 |
|
|
invalidate_buffers(Device);
|
1893 |
|
|
/*
|
1894 |
|
|
Clear existing partition sizes.
|
1895 |
|
|
*/
|
1896 |
|
|
if (PartitionNumber > 0)
|
1897 |
|
|
{
|
1898 |
|
|
Controller->GenericDiskInfo.part[MinorNumber].start_sect = 0;
|
1899 |
|
|
Controller->GenericDiskInfo.part[MinorNumber].nr_sects = 0;
|
1900 |
|
|
}
|
1901 |
|
|
/*
|
1902 |
|
|
Reset the Block Size so that the partition table can be read.
|
1903 |
|
|
*/
|
1904 |
|
|
set_blocksize(Device, BLOCK_SIZE);
|
1905 |
|
|
}
|
1906 |
|
|
resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
|
1907 |
|
|
return 0;
|
1908 |
|
|
}
|
1909 |
|
|
return -EINVAL;
|
1910 |
|
|
}
|
1911 |
|
|
|
1912 |
|
|
|
1913 |
|
|
/*
|
1914 |
|
|
DAC960_GenericDiskInit is the Generic Disk Information Initialization
|
1915 |
|
|
Function for the DAC960 Driver.
|
1916 |
|
|
*/
|
1917 |
|
|
|
1918 |
|
|
static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *GenericDiskInfo)
|
1919 |
|
|
{
|
1920 |
|
|
DAC960_Controller_T *Controller =
|
1921 |
|
|
(DAC960_Controller_T *) GenericDiskInfo->real_devices;
|
1922 |
|
|
DAC960_LogicalDriveInformation_T *LogicalDriveInformation =
|
1923 |
|
|
Controller->LogicalDriveInformation
|
1924 |
|
|
[Controller->LogicalDriveInformationIndex];
|
1925 |
|
|
int LogicalDriveNumber;
|
1926 |
|
|
for (LogicalDriveNumber = 0;
|
1927 |
|
|
LogicalDriveNumber < Controller->LogicalDriveCount;
|
1928 |
|
|
LogicalDriveNumber++)
|
1929 |
|
|
GenericDiskInfo->part[DAC960_MinorNumber(LogicalDriveNumber, 0)].nr_sects =
|
1930 |
|
|
LogicalDriveInformation[LogicalDriveNumber].LogicalDriveSize;
|
1931 |
|
|
}
|
1932 |
|
|
|
1933 |
|
|
|
1934 |
|
|
/*
|
1935 |
|
|
DAC960_Message prints Driver Messages.
|
1936 |
|
|
*/
|
1937 |
|
|
|
1938 |
|
|
static void DAC960_Message(DAC960_MessageLevel_T MessageLevel,
|
1939 |
|
|
char *Format,
|
1940 |
|
|
DAC960_Controller_T *Controller,
|
1941 |
|
|
...)
|
1942 |
|
|
{
|
1943 |
|
|
static char Buffer[DAC960_LineBufferSize];
|
1944 |
|
|
static boolean BeginningOfLine = true;
|
1945 |
|
|
va_list Arguments;
|
1946 |
|
|
int Length = 0;
|
1947 |
|
|
va_start(Arguments, Controller);
|
1948 |
|
|
Length = vsprintf(Buffer, Format, Arguments);
|
1949 |
|
|
va_end(Arguments);
|
1950 |
|
|
if (MessageLevel == DAC960_AnnounceLevel)
|
1951 |
|
|
{
|
1952 |
|
|
static int AnnouncementLines = 0;
|
1953 |
|
|
strcpy(&Controller->MessageBuffer[Controller->MessageBufferLength],
|
1954 |
|
|
Buffer);
|
1955 |
|
|
Controller->MessageBufferLength += Length;
|
1956 |
|
|
if (++AnnouncementLines <= 2)
|
1957 |
|
|
printk("%sDAC960: %s", DAC960_MessageLevelMap[MessageLevel], Buffer);
|
1958 |
|
|
}
|
1959 |
|
|
else if (MessageLevel == DAC960_InfoLevel)
|
1960 |
|
|
{
|
1961 |
|
|
strcpy(&Controller->MessageBuffer[Controller->MessageBufferLength],
|
1962 |
|
|
Buffer);
|
1963 |
|
|
Controller->MessageBufferLength += Length;
|
1964 |
|
|
if (BeginningOfLine)
|
1965 |
|
|
{
|
1966 |
|
|
if (Buffer[0] != '\n' || Length > 1)
|
1967 |
|
|
printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
|
1968 |
|
|
Controller->ControllerNumber, Buffer);
|
1969 |
|
|
}
|
1970 |
|
|
else printk("%s", Buffer);
|
1971 |
|
|
}
|
1972 |
|
|
else
|
1973 |
|
|
{
|
1974 |
|
|
if (BeginningOfLine)
|
1975 |
|
|
printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
|
1976 |
|
|
Controller->ControllerNumber, Buffer);
|
1977 |
|
|
else printk("%s", Buffer);
|
1978 |
|
|
}
|
1979 |
|
|
BeginningOfLine = (Buffer[Length-1] == '\n');
|
1980 |
|
|
}
|